Java 21个锁的概念

今天逛知乎看到一个不错的文章,文章的标题其实不太贴切,其实并不是按同一分类方法有21种锁,而是按不同方法分类的。不过以前从没想过竟然有这么多锁的概念:)

先帖地址:https://zhuanlan.zhihu.com/p/215271906

以下是一些总结和理解,有些关键或自己理解深的照抄原文:)

悲观 vs 乐观

悲观锁是通常意义上的锁,无论读写均锁定,一致性得到保证。如:Synchronized;

乐观锁则认为读多写少,读写冲突概率低,所以读时不锁,仅写时锁。乐观锁在更新前会把目标值与期望值做比较,仅当一致时更新(锁定)。如:CAS。

自旋

自旋只一种锁的等待方案。一般的线程当遇到资源已经被锁定时,直接切换线程环境,把CPU资源交给其它线程。而自旋则是线程空转,等待资源释放。适用于:1)多核(线程)结构CPU,单核显然是不适用的;2)资源使用时间短,快速释放的场合。

自旋锁,有一个自旋次数配置(-XX:PreBlockSpin),当超过特定的次数,线程仍未等到资源释放,则切换线程资源。JVM默认为10,可配置。同时,可配置为自适应自旋,根据上次旋转的次数等参数来动态调整这个次数。

CAS使用自旋锁。

可重入锁

可重入锁表示同一线程可以多次获取同一锁。如:ReentrantLock,Synchronized是可重入的。

读写锁

读写分离锁;读锁定时允许多线程读,一旦写锁定,则与悲观锁相同(不可再获取读锁)。

公平锁VS非公平锁

公平锁,线程请求某个资源时如遇到锁,则会进行排除,按FIFO的顺序依次获取资源;非公平锁:没有队列,谁先获得锁是不一定的。

非公平锁效率更高,但可能导致某些线程始终不能得到锁(线程饥饿)。synchronized是非公平锁,ReentrantLock通过构造函数指定该锁是公平的还是非公平的,默认是非公平的。

共享锁

用ReentrantReadWriteLock实现,其实就是乐观锁,读写锁的意思。

独占锁/互斥锁/同步锁===悲观锁

与悲观锁,互斥锁同义,即同一时刻只有一个线程能获取资源。synchronized,ReentrantLock

重量级 VS 轻量级锁

通过锁的实现方式区分锁的类型。

synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本身依赖底层的操作系统的 Mutex Lock来实现。操作系统实现线程的切换需要从用户态切换到核心态,成本非常高。这种依赖于操作系统 Mutex Lock来实现的锁称为重量级锁。为了优化synchonized,引入了轻量级锁偏向锁

轻量级锁是JDK6时加入的一种锁优化机制: 轻量级锁是在无竞争的情况下使用CAS操作去消除同步使用的互斥量。轻量级是相对于使用操作系统互斥量来实现的重量级锁而言的。轻量级锁在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。如果出现两条以上的线程争用同一个锁的情况,那轻量级锁将不会有效,必须膨胀为重量级锁。出现此情形时,轻量级锁性能要差于重量级锁。

偏向锁,则是轻量级锁的进一步优化,如果资源没有竞争,且总是倾向于使用同一个线程处理,则可以使用偏向锁。偏向锁会连CAS也忽略掉。

分段锁

一次不把所有资源都锁定,类似库库的页面级和行级锁这样的。文中以ConcurrentHashMap为例,ConcurrentHashMap里面包含了多个(默认16)个HashMap,每一个HashMap就是一个segment,在锁定时先计算出KEY,确定属于哪个segment,然后只锁定这个segment,提高并发效率。

死锁:不用解释

锁粗化

如果一段连续代码中有几处需要锁定同一资源,没必要反复加锁,解锁,在增加开销的同时还增加了竞争的可能性,将锁定放到更大的范围(代码段),即为锁粗化,是一种锁优化技术。

锁消除

如果通过技术手段可以不用加锁,称之为锁消除,也是一种锁优化技术。

synchronized——Java关键字

关键字,独占(互斥,悲观)锁,可重入锁,非公平锁。

作用于实例方法时,锁定一个对象;作用于静态方法时,锁定Class类,相当于全局锁。

作用于一个非null的对象实例时,锁定所有以该对象为锁的代码块。

Lock——Java接口

Java中的接口,属于可重入,悲观(独占,互斥,同步)锁。

需要手动获取和释放,而synchronized是完全自动的(锁定相当的代码段)

synchronized出现异常时,自动释放当前线程锁,不会导致死锁;而lock发生异常需要捕获并手动释放锁(unLock),因此建议在finally块中释放锁。

lock可以让等待线程响应中断,而synchornized会一直等待。

lock可以知道是否获取成功锁,而synchronized则不行。

lock可通过读写锁,实现共享锁,提高效率。

ReentrantLock——Lock的实现类

ReentrantLock是一个类,继承了lock接口,是可重入,悲观锁(同步,互斥,独占)。

ReentrantLock可以实现公平与非公平锁,而synchornized则只能是非公平锁。

ReentrantLock可通过Condition绑定多个条件。

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *