Java同步-互斥锁.等待vs列表,等待



当使用Java线程原语构造线程安全的有界队列时-这两种构造有什么区别

  1. 创建显式锁对象。
  2. 使用列表作为锁并等待。

1

示例
private final Object lock = new Object();
private ArrayList<String> list = new ArrayList<String>();
public String dequeue() {
    synchronized (lock) {
        while (list.size() == 0) {
            lock.wait();
        }
        String value = list.remove(0);
        lock.notifyAll();
        return value;
    }
}    
public void enqueue(String value) {
    synchronized (lock) {
        while (list.size() == maxSize) {
            lock.wait();
        }
        list.add(value);
        lock.notifyAll();
    }
}

2

示例
private ArrayList<String> list = new ArrayList<String>();
public String dequeue() {
    synchronized (list) {  // lock on list
        while (list.size() == 0) {
           list.wait();     // wait on list
        }
        String value = list.remove(0);
        list.notifyAll();  
        return value;
    }
}

public void enqueue(String value) {
    synchronized (list) {  // lock on list
        while (list.size() == maxSize) {
           list.wait();   // wait on list
        }
        list.add(value);
        list.notifyAll();
    }
}

注意

  1. 这是一个有界列表
  2. 没有其他操作正在执行,除了进入队列和退出队列。
  3. 我可以使用阻塞队列,但这个问题更多的是为了提高我有限的线程知识。
  4. 如果这个问题是重复的,请让我知道。

简短的回答是,不,除了维护额外锁对象的额外内存开销之外,没有功能上的区别。然而,在做出最终决定之前,我要考虑几个与语义相关的项目。

我是否需要执行同步操作,而不仅仅是我的内部列表?

假设您想要维护一个与ArrayList并行的数据结构,这样列表上的所有操作和并行数据结构都需要同步。在这种情况下,最好使用外部锁,因为列表或结构上的锁可能会对该类的未来开发工作造成混淆。

我是否会在我的队列类之外访问我的列表?

假设您想为列表提供一个访问器方法,或者使其对Queue类的扩展可见。如果使用外部锁对象,则检索到列表引用的类将永远无法对该列表执行线程安全操作。在这种情况下,最好在列表上同步,并在API中明确对列表的外部访问/修改也必须在该列表上同步。

我相信你会选择其中一个而不是另一个,但这是我能想到的两个最大的原因。

最新更新