synchronize(this)与自定义锁对象的区别及效率优劣分析
同步对象与同步实例的区别,以及两种同步方式的效率对比
咱们先把核心概念和区别掰扯清楚,再聊效率的事儿:
一、同步对象 vs 同步实例的核心区别
这里的「同步实例」其实就是指用当前对象实例(this)作为锁,而「同步对象」通常指专门定义的锁对象(比如例子里的LOCK),二者的核心差异体现在这几个方面:
- 锁的作用范围:
- 用
this作为锁时,锁的是当前类的单个实例——每个new出来的对象都有自己独立的锁,不同实例的同步块之间不会互相阻塞,适合实例状态独立的场景。 - 如果是
static final的LOCK,那锁的是整个类级别——所有该类的实例都会共享这一把锁,只要有一个实例进入同步块,其他实例的同一块代码都会被阻塞,适合全局状态同步的场景;如果LOCK是非static的,那也是实例级锁,但和this是完全独立的两个对象,不会和其他用this锁的代码冲突。
- 用
- 锁的安全性与可控性:
this是公开可访问的——外部代码完全可以拿到你的对象实例,然后也对它加锁,这会导致你完全意料之外的阻塞,比如外部的同步逻辑和你内部的同步块互相干扰,引发并发问题。- 自定义的
private static final Object LOCK是类内部私有锁,只有你自己的代码能使用它,从根源上避免了外部误用锁的风险,同步逻辑更可控、更安全。
- 与其他同步逻辑的兼容性:
- 如果你的类里还有用
synchronized修饰的实例方法,这些方法和synchronized(this)的同步块共用同一把锁——也就是说,调用同步方法会阻塞同步块,反之亦然,可能会限制并发能力。 - 自定义
LOCK是独立的锁对象,不会和同步方法、其他同步块的锁产生关联,能更灵活地拆分同步范围,提升并发度。
- 如果你的类里还有用
二、两种同步方式的效率对比
从JVM底层的锁获取/释放开销来看,两种方式的性能没有本质差异——都是基于对象监视器(monitor)的操作,耗时几乎一样。但从并发能力和安全性的角度,方式二更优:
- 方式一(
synchronize(this))的最大问题是锁暴露风险,外部的意外锁使用会降低并发效率,甚至引发死锁;而且和同步方法共享锁的特性,也会让原本可以并行的操作被迫串行。 - 方式二(自定义
LOCK)因为锁的私有性,完全避免了外部干扰,你可以精准控制哪些代码块共用同一把锁,不会出现不必要的阻塞。如果是类级别的static LOCK,能保证全局状态的一致性;如果是非static的,也能在实例级同步的同时,避免和其他同步逻辑冲突。
简单总结:如果追求绝对的安全和灵活的并发控制,优先选方式二;如果只是简单的实例级同步且能确保外部不会误用当前对象锁,方式一也能工作,但风险更高。
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

