20200407——java并发 偏向锁和重量级锁 八

踩坑误区

不管是synchronize用在对象或者类对象中,最后是在方法中。都是对对象加锁。获取他的实例方法。

1.6之前
之前的synchronized都是重量级锁,1.6改良了 ,先是偏向锁到轻量级锁,到最后的重量级锁。

偏向锁
不过,当线程执行到临界区(critical section)时,此时会利用**CAS(Compare and Swap)**操作,将线程ID插入到Markword中,同时修改偏向锁的标志位。

如果有线程获取到锁了。

在这里插入图片描述

那么,什么是偏向锁

偏向锁是jdk1.6引入的一项锁优化,其中的“偏”是偏心的偏。它的意思就是说,这个锁会偏向于第一个获得它的线程,在接下来的执行过程中,假如该锁没有被其他线程所获取,没有其他线程来竞争该锁,那么持有偏向锁的线程将永远不需要进行同步操作。

在此线程之后的执行过程中,如果再次进入或者退出同一段同步块代码,并不再需要去进行加锁或者解锁操作,而是会做以下的步骤:

Load-and-test,也就是简单判断一下当前线程id是否与Markword当中的线程id是否一致.

如果一致,则说明此线程已经成功获得了锁,继续执行下面的代码.

如果不一致,则要检查一下对象是否还是可偏向,即“是否偏向锁”标志位的值。

如果还未偏向,则利用CAS操作来竞争锁,也即是第一次获取锁时的操作。

锁膨胀

刚才说了,当出现有两个线程来竞争锁的话,那么偏向锁就失效了,此时锁就会膨胀,升级为轻量级锁。这也是我们经常所说的锁膨胀

锁撤销

由于偏向锁失效了,那么接下来就得把该锁撤销,锁撤销的开销花费还是挺大的,其大概的过程如下:

在一个安全点停止拥有锁的线程。

遍历线程栈,如果存在锁记录的话,需要修复锁记录和Markword,使其变成无锁状态。

唤醒当前线程,将当前锁升级成轻量级锁。

轻量级锁

锁撤销升级为轻量级锁之后,那么对象的Markword也会进行相应的的变化。下面先简单描述下锁撤销之后,升级为轻量级锁的过程:

线程在自己的栈桢中创建锁记录 LockRecord。

将锁对象的对象头中的MarkWord复制到线程的刚刚创建的锁记录中。

将锁记录中的Owner指针指向锁对象。

将锁对象的对象头的MarkWord替换为指向锁记录的指针。

轻量级锁分两种锁
自旋锁与自适应自选锁

自适应自旋锁

假如一个线程1刚刚成功获得一个锁,当它把锁释放了之后,线程2获得该锁,并且线程2在运行的过程中,此时线程1又想来获得该锁了,但线程2还没有释放该锁,所以线程1只能自旋等待,但是虚拟机认为,由于线程1刚刚获得过该锁,那么虚拟机觉得线程1这次自旋也是很有可能能够再次成功获得该锁的,所以会延长线程1自旋的次数。

轻量级锁也被称为非阻塞同步、乐观锁,因为这个过程并没有把线程阻塞挂起,而是让线程空循环等待,串行执行。

为什么说重量级锁开销大呢

主要是,当系统检查到锁是重量级锁之后,会把等待想要获得锁的线程进行阻塞,被阻塞的线程不会消耗cup。但是阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值