繁体   English   中英

这是不间断的双重检查锁定吗?

[英]Is this Double-Checked Locking that is not Broken?

本文介绍了“双重检查锁定”,其思想是减少锁定争用。 如文章所述,它不起作用。 请参阅表“(仍然)断掉的多线程版本“ Double-Checked Locking”惯用语”中的代码示例。

现在,我认为我发现了应该起作用的变体。 问题是那是否正确。 假设我们有一个使用者和一个生产者,它们通过一个共享队列交换数据:

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();
                }
            }
        }
    }
}

现在的问题是您是否认为此方法有效。 我要确保,因为如果不这样做,那么很多事情都会中断……这个想法是在updateCount发生变化的同时仅在使用者中输入同步块时减少锁争用。

我怀疑您正在寻找更多的《代码审查》

您应该考虑以下几点:

  • 这不是双重检查锁定。
  • 您的消费者将无动于衷,在没有数据到达时吃掉CPU。
  • 您将AtomicInteger用作信号量。
  • 一个BlockingQueue将为您完成所有这些工作。
  • 您尚未正确确保updateCount是共享的。
  • 您不必在原子上进行同步。

这是一个简单的生产者/消费者对进行演示。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM