我是否需要为ReentrantLock保护的size变量使用volatile?
问题解答
你的理解不完全正确,原因如下:
- ReentrantLock确实会建立happens-before关系:线程调用
unlock()的操作,happens-before于后续其他线程对同一锁的lock()操作。这意味着,当线程A执行完update()并解锁后,所有后续获取该锁的线程都能看到size的最新值。 - 但你的
size()方法没有加锁,这就存在问题:如果一个线程直接调用size()而不持有锁,它无法保证能看到其他线程通过update()更新的size值——该线程的缓存可能还保留着size的旧副本,没有从主内存同步最新数据。
正确的处理方式有两种:
- 给
size()方法也加上锁,确保每次读取size时都经过锁的同步:
public int size() { lock.lock(); try { return size; } finally { lock.unlock(); } }
- 将
size声明为volatile,利用volatile的可见性保证读取操作能获取主内存的最新值(注意:volatile不能保证size++的原子性,但这里update()已经通过锁保证了原子性,所以可以搭配使用):
volatile int size;
不过更推荐第一种方式,因为锁能同时保证原子性和可见性,逻辑更统一,也避免后续扩展时出现同步疏漏。
内容的提问来源于stack exchange,提问作者greenButMellow
相关产品推荐
相关产品推荐

