我从 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
这样的关键字是浅薄的。就像final
、static
、private
适用于当对数组的引用改变时,改变内容数组未被覆盖。
例如而不是
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/