[英]Is this Double-Checked Locking that is not Broken?
This article explains "Double-Checked Locking" where the idea is to reduce lock contention. 本文介绍了“双重检查锁定”,其思想是减少锁定争用。 As the article explains it does not work.
如文章所述,它不起作用。 See the code sample in the table "(Still) Broken multithreaded version "Double-Checked Locking" idiom".
请参阅表“(仍然)断掉的多线程版本“ Double-Checked Locking”惯用语”中的代码示例。
Now I think I found a variant that should work. 现在,我认为我发现了应该起作用的变体。 Question is whether that is correct.
问题是那是否正确。 Let's say we have a consumer and a producer that exchange data through a shared queue:
假设我们有一个使用者和一个生产者,它们通过一个共享队列交换数据:
class Producer {
private Queue queue = ...;
private AtomicInteger updateCount;
public void add(Data data) {
synchronized(updateCount) {
queue.add(task);
updateCount.incrementAndGet();
}
}
}
class Consumer {
private AtomicInteger updateCount = new AtomicInteger(0);
private int updateCountSnapshot = updateCount.get();
public void run() {
while(true) {
// do something
if(updateCountSnapshot != updateCount.get()) {
// synchronizing on the same updateCount
// instance the Producer has
synchronized(updateCount) {
Data data = queue.poll()
// mess with data
updateCountSnapshot = updateCount.get();
}
}
}
}
}
Question now is whether you think this approach works. 现在的问题是您是否认为此方法有效。 I'm asking to be sure, because tons of things would break if it doesn't ... The idea is to reduce lock contention when only entering a synchronized block in the consumer when the updateCount has changed in the meanwhile.
我要确保,因为如果不这样做,那么很多事情都会中断……这个想法是在updateCount发生变化的同时仅在使用者中输入同步块时减少锁争用。
I suspect you are looking more for a Code Review . 我怀疑您正在寻找更多的《代码审查》 。
You should consider the following: 您应该考虑以下几点:
updateCount
is shared. updateCount
是共享的。 Here's a simple Producer/Consumer pair for demonstration. 这是一个简单的生产者/消费者对进行演示。
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if (i != null) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.