常见锁策略
乐观锁 vs 悲观锁
描述的是两种不同的加锁态度
乐观锁:预测锁冲突的概率不高,因此做的工作就可以简单一些
悲观锁:预测锁冲突的概率较高,因此做的工作就要复杂一些
读写锁 vs 普通互斥锁
读写锁:读写锁分为两种情况
- 加读锁 : 如果多个线程同时读同一个变量不加锁也没事,那么就加读锁,读锁和读锁之间不会产生竞争
- 加写锁:当多个线程同时修改同一个变量那么就需要加锁,也就是写锁,写锁和写锁之间会产生竞争。
- 如果线程是读操作就加读锁,线程是写操作就加写锁,读锁和写锁之间也会产生竞争。
读的场景往往比较读,写的场景往往比较少,因此也就优化了效率
普通互斥锁:当两个线程竞争同一把锁就会产生等待
重量级锁 vs 轻量级锁
重量级锁:加锁解锁开销比较大,典型的涉及内核的加锁逻辑,开销就比较大
轻量级锁:加锁解锁开销比较小,典型的纯用户的逻辑,开销就比较小
自旋锁 vs 挂起等待锁
自旋锁:自旋锁就是典型的轻量级锁实现,自旋就是"忙等"消耗大量的CPU资源,反复询问当前锁是否就绪(获取锁很及时)
挂起等待锁:典型的重量级锁的实现,在锁准备的时候去做其它的事(获取锁不那么及时)
公平锁 vs 非公平锁
公平锁: 先来后到
操作系统默认的锁的调度,是非公平锁的情况,要想实现公平锁,需要引入额外的数据结构来记录线程加锁的顺序。
可重入锁 vs 不可重入锁
可重入锁:同一个线程针对同一把锁连续加锁两次,不会死锁
不可重入锁:同一个线程针对同一把锁连续加锁两次,会死锁
synchronized
- 既是乐观锁也是悲观锁
- 既是轻量级锁也是重量级锁
- 乐观锁是基于自旋锁实现的,悲观锁是基于挂起等待锁实现的
- synchronized是自适应的,初始时是乐观锁/轻量级锁/自旋锁,如果锁竞争不激烈就保持不变,如果锁竞争激烈synchronized会自动升级成悲观锁/重量级锁/挂起等待锁。
- 是普通互斥锁,不是读写锁
- 是非公平锁 (ReentrantLock是公平锁)
- 是可重入锁