为什么下面的生产者消费者代码不需要变量?

Vik*_*kas 3 java concurrency producer-consumer

我看到它的方式,生产者和消费者线程都可以单独缓存计数并因此做出错误的决定.如果变量不是volatile,count ++可能只是更新缓存吗?

class Buffer {
        private char [] buffer;
        private int count = 0, in = 0, out = 0;

        Buffer(int size)
        {
             buffer = new char[size];
        }

        public synchronized void Put(char c) {
             while(count == buffer.length) 
             {
                  try { wait(); }
                  catch (InterruptedException e) { } 
                  finally { } 
             } 
             System.out.println("Producing " + c + " ...");
             buffer[in] = c; 
             in = (in + 1) % buffer.length; 
             count++; 
             notify(); 
        }

        public synchronized char Get() {
             while (count == 0) 
             {
                  try { wait(); }
                  catch (InterruptedException e) { } 
                  finally { } 
             } 
             char c = buffer[out]; 
             out = (out + 1) % buffer.length;
             count--;
             System.out.println("Consuming " + c + " ..."); 
             notify(); 
             return c;
        }
  }
Run Code Online (Sandbox Code Playgroud)

Ole*_*leg 5

不,两个方法都使用synchronized关键字定义,这意味着它们永远不会同时执行,并且内存也将被同步.volatile对于在synchronized块内访问的变量,永远不需要.

如果我们将使用Java提供其他的同步机制,例如ReentrantReadWriteLock,而不是synchronized我们也没有必要volatile,因为正常使用的锁具有相同的内存保证(用官方语言发生,之前的关系).

内存一致性属性

"释放"同步器方法(如Lock.unlock,Semaphore.release和CountDownLatch.countDown)之前的操作发生在成功"获取"方法(例如Lock.lock,Semaphore.acquire,Condition.await和CountDownLatch)之后的操作之前. .await在另一个线程中的同一个同步器对象上.