乐观锁VS悲观锁

乐观锁:

默认数据不会被其它线程更改,在修改的时候再检查比如版本号、CAS算法。实现:
java.util.concurrent.atomic下均为CAS实现。

悲观锁:

即线程独占锁。实现如:synchronized关键字、ReentrantLock。

使用场景:

乐观锁适合读特别多的应用场景,可提高效率。
悲观锁适合于写多的场景,这种情况下使用乐观锁会导致线程冲突重试,反而降低效率。

1.版本号机制:

每次更新version+1,更新带上一个where条件,version=#{beforUpdateReadVersion};

2.CAS:

CAS为比较内存值与进行比较的值是否相等,相等即更新,不相等则自旋(即死循环等待内存值与进行比较的值相等)。
compareAndSet方法比较:


image.png

CAS存在的缺陷:

2.1CAS带来的ABA问题:即expected的值为A不一定代表内容没有被修改,有可能被修改为B后又改回为A。

2.2循环时间是要CPU空转的

2.3原则上只能保证一个变量的原子操作,AtomicStampedReference类出现后,可以将多个变量包装成为一个对象传入。它的构造器接收泛型的。
image.png

总结

synchronized在1.6以后的版本中做了许多优化,比如引入了偏向锁、轻量锁,线程会进入Lock-Free 队列、经历自旋->阻塞->竞争的过程,通过牺牲一定的公平性获得性能提升。因此比较适合于synchronized资源竞争相对较严重的情况,因为这种情况如果使用乐观锁、会导致CPU大量空转或者线程冲突大量的re-try。

你可能感兴趣的:(乐观锁VS悲观锁)