gpt4 book ai didi

java - 使用锁对象来同步我的成员变量

转载 作者:行者123 更新时间:2023-12-01 21:43:19 26 4
gpt4 key购买 nike

我正在研究 Java 中的一个更高级的主题,即多线程主题。

我看到很多代码使用单独的对象锁Object lock = new Object();来同步某些类数据成员。

package multithreading;

import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

class ProduceConsume {

private LinkedList<Integer> queue = new LinkedList<>();
private final int LIMIT = 10;
private final Object lock = new Object();

public void produce() throws InterruptedException {
int value = 0;

while (true) {

synchronized (lock) {
while (queue.size() == LIMIT) {
lock.wait();
}

queue.add(value++);
lock.notify();
}
}
}

public void consume() throws InterruptedException {
while (true) {
Thread.sleep(1000);

synchronized (lock) {
while (queue.size() == 0) {
lock.wait();
}

System.out.print("Size is: " + queue.size());
int value = queue.removeFirst();
System.out.println("; value is: " + value);

lock.notify();
}
}
}

}


public class ProducerConsumerWaitNotify {

public static void main(String[] args) throws InterruptedException {

ProduceConsume object = new ProduceConsume();

ExecutorService execuor = Executors.newFixedThreadPool(2);

execuor.submit(new Runnable() {

@Override
public void run() {
try {
object.produce();
} catch (InterruptedException ex) {
Logger.getLogger(ProducerConsumerWaitNotify.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
execuor.submit(new Runnable() {

@Override
public void run() {
try {
object.consume();
} catch (InterruptedException ex) {
Logger.getLogger(ProducerConsumerWaitNotify.class.getName()).log(Level.SEVERE, null, ex);
}
}
});

execuor.shutdown();
execuor.awaitTermination(1000, TimeUnit.DAYS);
}
}

为什么我们不应该锁定 LinkedList 对象本身?这不是我看到的使用这种技术的唯一例子。这是一个好的做法吗?

但是我觉得如果我有两个单独的类用于生产和消费,并且它将链表作为其构造函数的成员,那么我必须在此链表对象上进行同步,对吗?

我知道 concurrent 包中的类是线程安全的,但这不是我的问题,我是在询问上述两种方法之间的最佳实践?

最佳答案

你可以,因为它是你类(class)的私有(private)成员,只有你可以锁定它。如果你管理得好,那么用户就不会仅仅通过使用你的类的实例来导致死锁。如果该字段是公共(public)的,那么用户可以对其加锁,那么如果您在类内使用相同的字段进行同步,则可能会出现死锁。这就是为什么我们也不在 this 指针上加锁。

但是,使用单个对象进行锁定有几个原因:

您可以将对象命名为 controlLockerObject(用于序列化公共(public)访问)、listLockerObject(用于序列化对列表的访问)、updateLockerObject(用于序列化对用于更新某些内容的代码区域的访问)等。

您可以将对象声明为final,这样就不会意外替换或删除用于同步的对象。

关于java - 使用锁对象来同步我的成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36217361/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com