一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
悲观锁
每个线程对同一个资源进行操作的时候,都需要进行加锁,使用完资源之后释放锁。
优点:解决所有并发问题
缺点:不支持并发执行,效率很低
乐观锁
对同一个数据操作的时候,记录一个版本号。每次进行修改的时候更新这个版本号。然后所有线程进行更新操作的时候都需要判断该版本号和第一次获取的时候的版本号是否一致
2.1.2 自旋锁和适应性自旋锁
两者关系
后者是前者的补充(优化)
自旋锁的由来
线程1和线程2竞争锁。线程1没有获得锁,但是如果这个时候切换CPU去执行线程2释放锁。可能切换还没完成线程2就释放了锁。又得切换回来。所以如果CPU是多核的,就不如直接线程1先自己玩会并循环看着这个资源的释放(自旋)来获得锁
适应性自旋锁就是:线程1告诉了线程3我等了一会就等到了资源的释放,你也等会。本来线程3想等10。结果听了这话觉得有门,就准备等20s。(反之也是一样,线程1告诉线程3我等了10s还没等到,那你觉得线程3应该怎么办?)这里的10s只是举例子,默认是指自旋10次
所以自旋锁的本质其实是锁的优化也是一种乐观锁的实现过程
自旋锁的优缺点
如果这种代码执行的很快(锁释放的很快),这就避免了切换CPU带来的资源消耗。这就是优点
优点带来了缺点,如果这块代码执行的很慢,或者很多的线程竞争这个资源,这个时候就会导致这个自旋的线程一直消耗CPU资源在这玩不干活。
自旋锁的使用
在JDK1.4.2到JDK1.6之间的版本,需要手动使用-XX:+UseSpinning来开启。如果是JDK1.6之后就是默认开启的(自适应自旋锁)