锁策略
锁策略?锁机制?锁特性? 大概可以这么理解吧, 根据不同的使用场景和需求, 锁有不同的特性供实现者选择
也可以说是: 当出现锁竞争时, 不同加锁机制的特点
再或者说: 是锁的形容词
以下是几种常见的锁策略
乐观锁 vs 悲观锁
乐观锁: 预测锁的竞争不会很激烈, 因此会少做一些工作 (假设数据一般不会出现并发冲突, 因此当数据进行提交的时候, 才会对数据进行检测, 如果判断出现了并发冲突, 就返回信息给用户, 让用户决定如何去做)
乐观锁一般是基于 版本号 这样的机制来实现的, 就是该做的还是会做, 做完了会基于版本号回滚,报错 …
悲观锁: 预测锁的竞争会很激烈, 因此会多做一些工作 (每次使用数据都会上锁)
悲观锁是直接不让你用, 如果该资源已经被使用, 那么你就阻塞等待锁释放就好了
轻量级锁 vs 重量级锁
轻量级锁 加锁解锁 的开销比较小, 效率高 (多数情况下, 乐观锁也是一个轻量级锁)
重量级锁 加锁解锁 的开销比较大, 效率低 (多数情况下, 悲观锁也是一个重量级锁)
换句话说
效率高的锁就是轻量级锁
效率低的锁就是重量级锁
自旋锁 vs 挂起等待锁
自旋锁: 在产生所冲突时, 自旋锁会不断的尝试去竞争锁
挂起等待锁: 在产生冲突时, 挂起等待锁不会主动去竞争锁, 而是等锁资源被释放, 被动通知你可以来进行锁竞争
互斥锁 vs 读写锁
互斥锁: 例如 sychronized , 提供加锁和解锁两个操作, 如果一个线程加锁, 另一个线程也加锁, 就会产生阻塞
读写锁: 提供三种操作
- 针对读加锁
- 针对写加锁
- 解锁
读写锁中约定
- 读锁和读锁之间没有锁冲突
- 写锁和写锁之间有锁冲突
- 读锁和写锁之间有锁冲突
公平锁 vs 非公平锁
公平锁: 当一个线程结束对某个资源的占有, 由下一个线程来获取该资源, 而下一个线程所在的就绪队列, 是有序的, 先来先到, 依次获取锁
非公平锁: 当一个线程结束对某个资源的占用, 由就绪队列中的所有线程进行抢占式获取锁, 而不是按照时间顺序, 先到先得
可重入锁 vs 不可重入锁
可重入锁: 一个线程针对一把锁, 连续加锁多次不会产生死锁
不可重入锁: 一个线程针对一把锁, 连续加锁两次就会产生死锁
以 Synchronized 为例, 对应锁策略
- synchronized 既是悲观锁, 也是乐观锁 (默认是乐观锁, 如果锁竞争比较激烈, 就会变成悲观锁)
- synchronized 既是轻量级锁, 也是重量级锁 (默认是轻量级锁, 如果锁竞争比较激烈, 就会转变成重量级锁)
- synchronized 的轻量级锁, 是基于自旋锁的方式实现的
synchronized 的重量级锁, 是基于挂起等待锁实现的 - synchronized 是互斥锁
- synchronized 是非公平锁 (抢占式执行)
- synchronized 是可重入锁