
先来一张锁,转自美团
-
客观锁/悲观锁
- 悲观锁。认为自己在使用数据一定会发生竞争,因此获取数据时优先加锁。比如 Java 中的 synchronized 和 ReentrantLock。
- 乐观锁。认为自己在使用数据时不会发生竞争,只有在更新数据的时候才会去判断期间有没有其他线程更新了数据。适合读操作多,写操作比较少的场景。一般使用 CAS和版本号实现。比如 java.utils.concurrent.atomic 包下。比如AutomicInteger
-
自旋锁/适应式自旋锁
- 考虑到 cpu 线程和上下文切换的消耗,可以考虑自选锁即忙等待的方式去获得锁。Java 中的自旋锁通过 CAS 实现,比如AutomicInteger。
- 另外场景的自旋锁还有TicketLock、CLHlock和MCSlock。
- 适应式自旋锁是通过判断在相同的锁对象上上一次自旋的成功率和等待时间来适应式的调整本次自旋的时间或者直接跳过自旋进行阻塞。
-
无锁/偏向锁/轻量级锁/重量级锁
-
公平锁/非公平锁
- 关于公平锁和非公平锁,典型的是 ReentrantLock 的实现,即FairSync和NonfairSync。公平锁将抢占同一个锁的线程按照抢占的时候进行排队,当锁释放时,根据入队时间分配锁。非公平锁也有一个队伍,其不公平性在于如果锁释放的瞬间刚好有一个线程请求锁,那么就会插队获取锁而不需要进行排队。
-
可重入锁/非可重入锁
- ReentrantLock 和 synchronized 都是可重入锁,广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class)。
-
不可重入锁表示尝试获取锁的时候无视当前线程是否已经获得了锁。
可重入锁/不可重入锁
-
独享锁/共享锁
- 独享锁和共享锁的典型就是读写锁。即ReentrantReadWriteLock$WriteLock和ReentrantReadWriteLock$ReadLock。
网友评论