Java轻量级锁比重量级锁快吗
Java中的锁早已成为并发编程的核心模块之一。随着Java并发编程的广泛应用,对于锁的性能也变得越来越重要。在Java中,锁的分类主要分为重量级锁(Synchronized)和轻量级锁(CAS)两种。那么,Java轻量级锁比重量级锁快吗?
1. 概念区分
重量级锁:JVM中根据ObjectMonitor对象实现,JVM会为每一个ObjectMonitor对象分配一个内部的控制块——Monitor。每个Monitor拥有一个EntryList和WaitSet。EntryList用来存储获取锁失败的线程,WaitSet用来存储调用wait()方法而进入等待状态的线程。在每个Monitor中只会 存在一个Owner,如果线程成功获取了锁,那么这个线程就成为Owner;如果执行完释放锁,那么这个锁就不再有Owner。
轻量级锁:是在JVM中通过CAS(Compare and Swap/Compare and Exchange)实现的,这种锁的特点是不需要和操作系统挂钩,而完全是由JVM自己实现的。当线程获取CAS后,如果CAS成功(当前线程成功获取锁),就不必再去判断他人是否拥有锁,因为锁已经归调用线程所有,直接进去执行即可。如果CAS失败(即其他线程竞争锁成功),则表示数据竞争,那么JVM就暂停当前线程,将锁还原为重量级锁(也可能变为自旋锁)。
从上面的介绍可以看出,重量级锁和轻量级锁的实现机制和内部结构有很大的不同。这也导致了不同锁之间各自的性能优劣。
2. 性能对比
(1)资源消耗
重量级锁:重量级锁实现需要JVM将进入等待状态的线程挂起,并且需要在操作系统层面分配资源进行锁的管理,因此资源开销更大,效率更低。
轻量级锁:JVM实现通过CAS方式实现锁的判断和获取,避免了进程调度和切换给JVM带来的开销,但是轻量级锁需要消耗更多的CPU周期用于自旋,因此对于大多数应用程序来说,轻量级锁比重量级锁更快。
(2)使用场景
重量级锁:适用于被频繁使用的并发程序锁的设计,由于获取重量级锁需要等待线程挂起,因此在并发性不高的情况下使用也会非常合适,因为对于并发性不高的场景,重量级锁也不会超时等待很长时间。
轻量级锁:适用于线程争用不高的情况,对于较多的线程竞争来说,使用轻量级锁会增加CPU的使用率,用户对CPU资源的消耗增加会导致其他线程只能等待,从而降低应用程序整体性能。
3. 总结
Java中的锁机制主要分为重量级锁和轻量级锁,它们的实现过程和内部结构都有很大的差别,并且它们在性能方面的表现也有所不同。对于单线程程序和线程并发不高的情况,重量级锁显然更适合,而对于线程并发量大的处理场合,轻量级锁相对更优秀。因此在实际项目中选择合适的锁对于程序的性能优化起到了至关重要的作用。
