gpt4 book ai didi

java - 双重检查锁定而不创建对象

转载 作者:太空宇宙 更新时间:2023-11-04 07:29:25 25 4
gpt4 key购买 nike

我使用双重检查锁定 (DCL) 来避免在不需要时对对象进行同步。就我而言,我需要在某些缓冲区为空时进行同步,让“处理线程”等待“交付线程”再次通知它 - 否则,“处理线程”将循环运行而不做任何有用的事情。

两个线程共享这些对象:

Object bufferLock = new Object();
Queue<Command> commands = new ConcurrentLinkedQueue<>(); // thread safe!

线程 1(“传递线程”- 填充缓冲区):

while (true)
Command command = readCommand();
commands.add(command);
synchronize (bufferLock){
bufferLock.notify(); // wake up Thread 2 (if waiting)
}
}

线程 2(“处理线程”- 清空缓冲区):

while (true){
if (commands.peek() == null){ // not creating anything here
synchronized (bufferLock){
if (commands.peek() == null){ // also not creating anything
bufferLock.wait();
}
}
}
Command command = commands.poll();
processCommand(command);
}

现在,NetBeans 显示了有关 DCL 的警告,这让我更深入地研究了这个主题,因为我不知道 DCL 的概念 - 我刚刚开始自己​​使用它。

据我通过阅读互联网上的几篇文章了解到,使用此模式时存在 Java 错误,但所有示例都将其与延迟加载结合使用。在这些示例中,对象是在同步块(synchronized block)内创建的。在我的同步代码中,我不创建对象。

我的代码不安全吗? NetBeans 显示警告是否正确?请注意,NetBeans 有一个 bug之前和DCL有关,所以有点困惑。

最佳答案

您创建的模式(或者更确切地说,反模式!)并不严格构成双重检查锁定,它通常指的是对象引用从 null 开始,然后由需要引用它的第一个线程实例化的情况,仅在 null 检查后进行同步。严格来说,到 Java 5 为止,您都无法在 Java 中正确实现这一点(尽管由于大多数 JVM 的实现方式,您可能会意外地逃脱它)。从 Java 5 开始,您可以使用它,但它基本上没有意义。 (您可能对我不久前写的 article on double-checked locking in Java 感兴趣,它更详细地研究了这个问题。类加载器实际上具有内置同步功能,适用于您确实需要 DCL 之类的极少数情况。)

现在,这都是顺便说的。严格来说,这里的内容并不是真正的 DCL。

您确实遇到的问题是您正在尝试混合范例。 Java 并发库存在的理由通常是避免使用同步和等待/通知进行低级锁定。因此,您真正应该做的就是简单地使用 BlockingQueue 的某种风格并使用其内置的阻塞行为。再说一遍,除其他示异常(exception),我可以向您推荐一些material I have written on blocking queues .

关于java - 双重检查锁定而不创建对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17973330/

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