各种锁
公平锁和非公平锁
公平锁
每个线程按照调用lock的顺序依次获取锁, 获取锁之前先检查等待队列是否有线程, 如果没有线程尝试获取锁, 否则排队
非公平锁
线程获取锁的顺序不定, 与调用lock顺序无关, 直接尝试获取锁, 未成功再排队
例子
线程到达顺序 A->B->C
- A先到达获取锁
- B到达获取锁, 尝试获取失败, 进入排队队列
-
A释放锁唤醒B, 同时C到达
- 公平锁<br/>
C发现等待队列中有线程, 直接进入等待队列队尾排队挂起, B获取到锁 -
非公平锁<br/>
- 情况一: C一来直接尝试获取锁, B获取锁失败, 再次进入等待队列挂起
- 情况二: C一来直接尝试获取锁, B获取锁成功, C进入等待队列挂起
- 公平锁<br/>
悲观锁和乐观锁
悲观锁
每次获取数据之前先加锁, 结束之后再释放, 占据锁期间, 别人无法获取数据
乐观锁
获取数据时不加锁, 但是设定一个版本号, 执行完事务后, 与最初版本号进行比较, 如果相等说明数据没有被修改, 将版本号加一, 如果获取到的版本号小于最新版本号, 说明当前数据可能被修改过, 放弃本次操作, 重新操作
适用场景
当冲突较少发生时, 可以选择使用乐观锁, 节省了加锁的代价, 加大吞吐量; 但当冲突较多发生时, 选择乐观锁时则会经常Retry, 降低性能, 或者此时可以选用悲观锁
mysql实现
悲观锁实现
select from ... for update
乐观锁实现
在表中增加一个作为数据版本号的字段, 最好为每个需要乐观锁的字段单独设置一个版本号, 否则可能会造成不必的冲突
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。