谈谈你对Java线程同步方式的了解
Java面试题:谈谈你对Java线程同步方式的了解?
得分点:
synchronized、Lock
标准回答:
Java通过加锁的方式来实现线程同步,提供了两种主要的锁机制,即synchronized
和Lock
。
synchronized:
synchronized
是Java的内置锁机制,可以用于实现方法、静态方法和代码块级别的同步。锁对象的选择取决于加锁的位置:
- 加在普通方法上时,锁是当前实例(
this
)。 - 加在静态方法上时,锁是当前类的
Class
对象。 - 加在代码块上时,需要在关键字后的小括号中显式指定一个对象作为锁对象。
不同的锁对象意味着不同的锁粒度,因此应根据需求选择适当的锁对象,以确定锁的范围和精度,以降低锁带来的性能开销。
Lock:
Lock
是Java提供的更高级别的锁机制,通过java.util.concurrent.locks
包实现。与synchronized
不同,Lock
提供了更多的灵活性和功能,包括:
- 支持响应中断。
- 支持超时机制。
- 支持非阻塞方式获取锁。
- 支持多个条件变量,允许线程在条件不满足时进入等待状态。
由于synchronized
在设计时未考虑到这些功能,要为其添加这些功能将涉及大规模的语法结构变更,这对于向后兼容旧代码是不利的。因此,Java在1.5版本引入了Lock
接口,以支持这些功能,并提供了更灵活的锁定机制。
加分回答:
在内部实现方面,synchronized
和Lock
采用了不同的策略来确保线程同步。
synchronized
采用“CAS+Mark Word”实现,同时使用锁升级机制以减少锁的开销。在高度竞争的多线程环境中,synchronized
会逐步升级锁的状态,从无锁、偏向锁、轻量级锁到重量级锁。Lock
则采用“CAS+volatile”实现,核心是AbstractQueuedSynchronizer
(AQS),它是线程同步的基础框架。具体的Lock
实现通过继承AQS来实现,并根据不同的使用场景派生出公平锁、非公平锁、读锁、写锁等具体的实现。
选择合适的锁取决于具体的需求和性能考虑。synchronized
在许多情况下非常方便,但Lock
提供了更多高级功能,特别适用于复杂的同步需求。