Java同步对象属性:synchronized是否会获取所有关联对象锁?
问题解答
核心结论
- 使用
synchronized(this)在UserImpl的临界区中,只会获取当前UserImpl实例的内置锁,不会自动获取其属性ServerState实例的锁。每个Java对象的内置锁是完全独立的,synchronized(对象)仅针对指定对象的锁生效,和该对象的成员对象没有关联。
对AdminImpl临界区的影响
你的第二个疑问的答案是否定的:AdminImpl的临界区不会因为UserImpl使用synchronized(this)而被阻塞,原因如下:
- 如果AdminImpl的临界区使用
synchronized(this):它获取的是AdminImpl实例自己的锁,和UserImpl的锁完全无关,两个类的临界区可以同时执行,互不干扰。 - 如果AdminImpl的临界区是为了保护ServerState的操作,使用
synchronized(serverState):此时只有当UserImpl的代码中也主动获取ServerState的锁时,才会产生竞争。但UserImpl用synchronized(this)的话,根本没有尝试获取ServerState的锁,所以AdminImpl可以正常进入自己的临界区。
正确同步共享ServerState的做法
如果你想要同步的是共享的ServerState实例(因为它同时被AdminImpl和UserImpl持有),正确的做法是在两个类的临界区中,都使用synchronized(serverState)来包裹操作ServerState的代码。这样所有访问该ServerState实例的临界区都会竞争同一个锁,保证共享状态的线程安全。
补充说明文档提示
你提到的文档中“避免同步调用其他对象的方法”,指的是如果在synchronized块内调用其他对象的方法,若该方法本身也持有锁,可能会导致锁嵌套,进而引发死锁等活性问题。但这和“自动获取成员对象的锁”是完全不同的概念——锁的获取始终是显式指定对象的,不会自动传递到成员对象。
内容的提问来源于stack exchange,提问作者chilliefiber
相关产品推荐
相关产品推荐

