各种锁

公平锁和非公平锁

公平锁

每个线程按照调用lock的顺序依次获取锁, 获取锁之前先检查等待队列是否有线程, 如果没有线程尝试获取锁, 否则排队

非公平锁

线程获取锁的顺序不定, 与调用lock顺序无关, 直接尝试获取锁, 未成功再排队

例子

线程到达顺序 A->B->C

  1. A先到达获取锁
  2. B到达获取锁, 尝试获取失败, 进入排队队列
  3. A释放锁唤醒B, 同时C到达

    • 公平锁<br/>
      C发现等待队列中有线程, 直接进入等待队列队尾排队挂起, B获取到锁
    • 非公平锁<br/>

      • 情况一: C一来直接尝试获取锁, B获取锁失败, 再次进入等待队列挂起
      • 情况二: C一来直接尝试获取锁, B获取锁成功, C进入等待队列挂起

悲观锁和乐观锁

悲观锁

每次获取数据之前先加锁, 结束之后再释放, 占据锁期间, 别人无法获取数据

乐观锁

获取数据时不加锁, 但是设定一个版本号, 执行完事务后, 与最初版本号进行比较, 如果相等说明数据没有被修改, 将版本号加一, 如果获取到的版本号小于最新版本号, 说明当前数据可能被修改过, 放弃本次操作, 重新操作

适用场景

当冲突较少发生时, 可以选择使用乐观锁, 节省了加锁的代价, 加大吞吐量; 但当冲突较多发生时, 选择乐观锁时则会经常Retry, 降低性能, 或者此时可以选用悲观锁

mysql实现

悲观锁实现
select from ... for update
乐观锁实现

在表中增加一个作为数据版本号的字段, 最好为每个需要乐观锁的字段单独设置一个版本号, 否则可能会造成不必的冲突


nwj_step
41 声望3 粉丝

暂时先写点东西吧


« 上一篇
JAVA快速复习
下一篇 »
Druid入门