java - 使用java ReentrantLock的时候需要给变量添加 volatile 吗?

标签 java multithreading

我从 Java8 Condition 看到下面的代码,我有一个问题:

由于put()take()方法可能会被多个线程同时调用,是否需要添加volatile 变量以获得正确的值?

例如:
对于数组items,如果两个线程调用put()向其中添加元素,另一个线程调用take()从中获取元素那么,是否会出现take()没有从主存获取最新数据的情况呢? 程序如何确保线程调用 take() 始终获得正确大小的 items

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   //shall we need to add volatile to the variables below
   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

最佳答案

volatile 这样的关键字是浅薄的。就像finalstaticprivate适用于当对数组的引用改变时,改变内容数组未被覆盖。

例如而不是

Object[] array;

array[0] = "hello";

如果更改为final

final Object[] array;

array[0] = "hello"; // I can still alter the array referrenced

如果更改为 volatile

volatile Object[] array;

array = new Object[1]; // a write barrier is added as I wrote to array
array[0] = "hello"; // I didn't change the array reference so no write barrier

Since the method put() and take() might be invoked by multiple thread at the same time,shall we need to add volatile to the variables in order to get the right value?

正确使用ReeenrantLock将添加您需要的读/写屏障。

关于java - 使用java ReentrantLock的时候需要给变量添加 volatile 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53296346/

相关文章:

c# - 捕获 ThreadAbortException 时隐藏的 Throw 有什么用?

python - 多线程模块比 python 中的多处理慢

multithreading - Python在休眠时终止线程

java - Hibernate-search 5.0 空间 - 不确定它是否在哈希中存储纬度/经度

Java - 使用 SpringLayout 的 JScrollPane View 布局

java - 从注释处理器应用 CGLib 代理

java - 在java中并行构造XML元素

java - 在 java 中将对象列表转换为 JSON 数组 - Spring Boot api 测试

java - 当两个单独的模式具有相同的命名空间时,如何告诉 JAXB 在单独的包中生成类?

c++ - 使用类构造函数在线程中启动成员函数