【发布时间】:2013-07-31 14:34:59
【问题描述】:
我正在使用双重检查锁定 (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 错误,但所有示例都将其与延迟加载结合使用。在这些示例中,对象是在同步块中创建的。在我的同步代码中,我不创建对象。
我的代码不安全吗? NetBeans 在显示警告方面是否正确?请注意,NetBeans 之前有一个与 DCL 相关的bug,所以我有点困惑。
【问题讨论】:
-
这与使用内置执行器相比如何?这包含了一个线程池(可以是一个)和 Runnable 队列来运行。如果你确信它比内置库做同样的事情更好,我只会写你自己的;)
-
另一点:您似乎正在重新发明已经为队列实现的阻塞操作。为什么?
-
DCL 的 java 错误是否仅与对象创建有关(在单例模式中)?
-
@Heuster 是的,这绝对是关于 DCL 的误报。
-
可以使用单线程的
Executor,没问题。
标签: java multithreading synchronized