锁的优化(偏向锁、轻量级锁、重量级锁,CAS)

本文介绍了Java并发中的锁优化策略,包括偏向锁、轻量级锁和重量级锁,以及CAS(Compare and Swap)操作。在JDK1.6后,为了解决synchronized的性能问题,引入了自适应自旋、锁消除和锁粗化等优化。CAS操作作为乐观锁的一种实现,避免了线程阻塞,但在多线程竞争下可能引发自旋浪费CPU资源。文章还探讨了CAS的ABA问题和公平性问题,并提到了如何关闭偏向锁以及轻量级锁的获取和解锁过程。
摘要由CSDN通过智能技术生成

为什么出现CAS?

我们知道synchronized关键字不论是实现同步方法还是同步代码块,都需要首先执行monitorenter获取到锁对象的监视器monitor,同一时刻只有一个线程可以获取到锁对象的monitor监听器,退出时需要执行monitorexit进行解锁。
monitor机制是JDK1.6之前synchronized(内建锁)底层原理,又称为JDK1.6重量级锁。线程的阻塞和唤醒均需要操作系统由用户态切换到内核态,开销十分大,因此效率很低。并且是JVM层面锁。

基于上面原因,在JDK1.6对内建锁有了以下优化:自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。
锁优化后,并不是不需要等待,只是等待时间变短

在理解锁优化之前先了解2个概念:CAS操作和Java对象头。

什么是CAS(Compare and Swap)?
在介绍CAS前,先简单看一下乐观锁和悲观锁。

悲观锁:JDK1.6以前线程获取内建锁(synchronized)是一种悲观锁策略。
悲观锁顾名思义就是运气很差,只要我需要锁,就有其他线程和我争抢锁~~
每一次访问临界资源都会发生冲突,如果我费九牛二虎之力获取到锁后,我获取到锁的同时会阻塞其他未获取到锁线程。

乐观锁:乐观锁是所有线程访问共享资源都不会发生冲突,既然不会发生冲突就不会阻塞其他线程,那么线程不会出现阻塞等待的状态。
每次操作都认为不会发生冲突,尝试执行,并检测结果是否正确。如果正确则执行成功,否则发生了冲突,回退再重新尝试直到没有冲突。其实重试时间很快,差不多几毫秒,这个线程在尝试的过程一直在cpu上跑,只是跑的是无用指令,那么就没有从用户态切换到内核态,开销因此变小。

在Java多线程中,乐观锁一个常见实现是CAS操作。

CAS操作过程:
CAS(比较交换)。
其具有三个操作数:

  • V:当前内存地址实际存放的值;
  • O:内存存放预期值(旧值);
  • N :更新的新值。

当V=0,预期值和内存实际值相等,内存存放的实际值没有被任何其他线程修改,即O就是目前最新的值,可以将新值N赋给V;

当V!=O,表明内存存放的实际值已经被其他线程修改,因此O值不是当前最新值,返回V,无法修改。(将V返回是因为再次重试时期待值就变为V)

可以将上述情况简单举一个例子:
比如说去餐厅买饭,正在买饭的同学是小米,我期望的人也是小米,小米买完就轮到我买,可以这个时候我去餐桌放书包,回来发现买饭的同学不是小米而是小明,也就是说预期值和实际值不同,那么就轮不到我买饭~~但是我会知道现在实际买饭的同学是小明,那我在等会,小明买完就是我买 ~ ~
如果回来小米刚好买完,我就可以买饭,也就是说现在实际买饭的人更新为我。开心,终于可以买饭了~ ~

当多个线程使用CAS操作时一个变量时,只有一个线程会成功,并成功更新,其余线程均会失败。失败的线程会重新尝试(自旋),当然也可以选择重新挂起(阻塞)。

内建锁和自旋锁区别:
没有优化的synchronized(内建锁)的主要问题是:在存在线程竞争的情况下会出现线程的阻塞和唤醒带来的性能问题,这是一种互斥同步(阻塞同步);
而CAS操作失败后,并不是武断的将线程挂起,失败后会进行一定的尝试,而非耗时的将线程挂起,因此CAS也称为非阻塞同步。

CAS存在问题
1.ABA问题:
比如一个线程1从内存位置V取出A,这时候另一个线程2也从内存中取出A,并且线程2进行了一些操作变成B,然后线程2又将内存位置V的数据变为A,这时候线程1进行CAS操作发现内存中仍然是A,然后线程1操作成功。尽管线程1的CAS操作成功,但是并不代表这个过程没有问题。如果链表的头在变化了2次后恢复了原值,但是并不代表链表没有变化。
对于ABA问题解决办法是添加一个版本号,对上述例子是将2个A进行不同的标记比如A1,A2等,由于版本号不同,线程1无法操作成功。在JDK1.5之后使用atomic包中提供的AtomicStampedReference 类来解决。

2.自旋会浪费大量的CPU资源:
与阻塞线程相比,自旋会浪费大量的处理器资源。因为当前

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值