多线程中线程获取单个对象锁是否等同于持有该类所有对象的锁?
问题修正
原问题未明确访问的是实例的需要持有对象锁的同步资源,如果是访问普通非同步属性/方法,本来就不会触发锁竞争,因此优化后的严谨表述为:
在基于对象锁实现同步的多线程场景(以Java为例)中,若某一线程已经获取类A的实例
a1的对象锁,此时另一个线程新建类A的实例a2,并尝试访问a2的同步方法/需要持有a2对象锁的代码块,是否会受到前者持有的锁的限制?
解答
- 正常情况下完全不会受到限制。对象锁是和具体实例绑定的,每个实例的对象锁都是独立的,互不影响。
- 线程持有
a1的对象锁时,只会阻塞其他尝试获取a1锁的操作,和其他实例的锁没有任何关联。线程2操作a2的同步资源时,只需要竞争a2自己的对象锁即可,不需要等a1的锁释放。 - 只有一种特殊情况会出现跨实例的锁限制:你用的是类锁而非实例对象锁,比如同步方法加了
static修饰,或者同步块锁定的是A.class全局类对象,此时所有该类的实例同步资源都共用同一把类锁,才会互相阻塞。
可以参考下面的测试代码验证结论:
public class LockTest { // 实例级同步方法,锁为当前类实例对象 public synchronized void instanceSync() { System.out.println(Thread.currentThread().getName() + " 开始执行实例同步方法"); try { // 模拟业务执行2秒 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 执行结束"); } public static void main(String[] args) throws InterruptedException { LockTest instance1 = new LockTest(); // 线程1先拿到instance1的锁,执行2秒 new Thread(instance1::instanceSync, "线程1").start(); // 保证线程1先启动并拿到锁 Thread.sleep(100); LockTest instance2 = new LockTest(); // 线程2操作instance2,不会被阻塞 new Thread(instance2::instanceSync, "线程2").start(); } }
运行代码后会看到两个线程的「开始执行」日志几乎同时打印,间隔远小于2秒,验证实例锁互不干扰的结论。
内容的提问来源于stack exchange,提问作者chathala anil
相关产品推荐
相关产品推荐

