Java 同步 - Mutex.wait 与 List.wait

标签 java synchronization

在使用 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 维护一个并行数据结构,这样列表上的所有操作和该并行数据结构都需要同步。在这种情况下,最好使用外部锁,因为锁定列表或结构可能会对此类的 future 开发工作造成混淆。

我会在我的队列类之外授予对我的列表的访问权限吗?

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

我敢肯定,您可能会选择一个而不是另一个的原因有很多,但这是我能想到的两大原因。

关于Java 同步 - Mutex.wait 与 List.wait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16970055/

相关文章:

java - Hibernate自引用关系和延迟加载

java - Java/Glassfish 日志文件的远程日志查看器

c# - 我如何才能同时打开两个连接以在 c# 中同步两个数据库 mysql?

c# - 每天同步不同机器上的两个 SQL Server 数据库有什么好方法吗?

java.text.Parse 异常 : Unparseable Date

java - Java 中四舍五入到偶数个小数点

c - 多线程 C/C++ 变量无缓存 (Linux)

Java同步方法调用非同步方法

mysql - 如何使用 galera 集群测试关键读取和慢速同步

java - 在应用程序的整个 Activity 中管理持久视觉数据(事件驱动的按钮和 ImageView )