多线程访问类成员的锁范围疑问:锁父类还是专属变量?
问题解答
核心结论
如果能严格保证每个变量只被唯一的专属线程访问,那完全不需要加锁;如果出于防御性编程考虑要加锁,优先选择仅锁定被访问的变量(或对应独立锁对象),绝对不要锁定整个父类。
详细分析
无锁才是最优选择
线程对自己专属变量的读写操作,只要没有其他线程参与,不存在任何线程安全问题——不管是内存可见性还是数据竞争,都不会发生。这种情况下加锁纯粹是浪费性能,完全没必要。绝对不要锁定整个父类
锁定整个父类(比如用synchronized修饰父类方法,或者锁父类的class对象)会导致所有线程的操作强制串行化,哪怕它们访问的是完全不相关的变量。这会把多线程的并发优势彻底废掉,属于典型的过度同步。锁定专属变量的防御性方案
如果担心后续代码改动不小心打破“专属线程”的规则,或者需要留有余地,给每个变量分配一个独立的锁对象是更合理的做法:- 每个线程只锁住自己要访问的变量对应的锁,不会影响其他线程的操作,并发性能不受影响;
- 即使未来出现意外的跨线程访问,也能通过锁保证线程安全。
举个Java代码示例:
class ParentClass { // 专属线程1的变量 private int varForThread1; private final Object lockForThread1 = new Object(); // 专属线程2的变量 private int varForThread2; private final Object lockForThread2 = new Object(); // 线程1调用的更新方法 public void updateVar1(int value) { synchronized(lockForThread1) { varForThread1 = value; } } // 线程2调用的更新方法 public void updateVar2(int value) { synchronized(lockForThread2) { varForThread2 = value; } } }
关键提醒
务必确认“每个变量仅由一个专属线程访问”的规则被严格执行——如果这个前提不成立,那独立锁的方案依然比全局锁更能兼顾安全与性能。
内容的提问来源于stack exchange,提问作者Chris Cao
相关产品推荐
相关产品推荐

