C/C++教程

synchronized锁及其锁升级

本文主要是介绍synchronized锁及其锁升级,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。

文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。

多线程加锁有两种方式

  • 利用Sychronized关键字
  • 利用Lock接口子类ReentrantLock类
Sychronized关键字与Lock接口比较
  • sychronized是java内置的关键字,查看不到线程是否获取到了锁;Lock接口是一个java接口,可以查看是否获取到了锁
  • synchronized可以加在方法、代码块上;Lock接口写在代码里;
  • synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
  • synchronized加在方法、代码块上,同一时刻只能有一个线程使用这段代码,其他线程必须等待,并且其他线程不能响应中断(响应中断=中断等待的状态:将线程从等待状态变为就绪状态,以便线程能继续往下执行代码;线程响应中断后会抛出一个异常,业务代码必须手动处理该异常);而Lock接口可以响应中断
  • Lock接口必须手动调用unlock()释放锁,否则容易造成死锁想象,一般在finally中调用unlock();

    synchronized放弃锁只有两种情况:

    (1)线程执行完了同步代码块的内容

    (2)发生异常;而lock不同,它可以设定超时时间,也就是说他可以在获取锁时便设定超时时间,如果在你设定的时间内它还没有获取到锁,那么它会放弃获取锁然后响应中断操作。
  • lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

synchronized锁升级

基础知识

每个【锁=锁对象】的对象头由两部分组成:Classpointer+Markword

(1)Classpointer=对象类型指针,JVM就是通过它来确定当前对象是属于哪个class实例

(2)Markword,32位的jvm中Markword是占4B=4byte=32b=32位,存放对象运行时的数据(对象gc时的分代年龄,对象hashcode,当前锁为偏向锁时的线程ID),synchronized锁机制与32位中的最后3位(1+2)密切相关,最后2位是普通锁位,倒数第三位是偏向锁位:
image
当锁对象被创建出来,此时锁对象为无锁状态,(偏向锁位,普通锁位)=(0,01),所有无锁对象都是可偏向的,即可以被任意线程加偏向锁,当第一个线程对该锁对象加锁时,会把偏向锁位由0变1代表偏向锁生效,同时把线程ID插入锁对象头的Markword中

synchronized锁升级的过程(无锁->...->重量级锁)

锁膨胀的过程:无锁(没有线程)->偏向锁(1个线程)->轻量级锁(有第二个及以上的线程竞争锁)->重量级锁(有三个及以上的线程竞争锁)

偏向锁

如何加锁:线程A第一次访问同步代码块中的代码时,先检查当前锁是否可偏向(偏向锁位为0),是则通过CAS获取锁,获取锁之后会在synchronized关键字对应的锁对象的对象头中,在Markword里记录本线程ID,线程A再次访问该同步代码块中的代码时,直接比较锁对象头的Markword的线程ID是否是本线程ID,若是则线程A可重入取锁进而直接访问同步代码块,否则说明是另外一个线程B想访问同步代码块,从而B竞争同一个【锁=锁对象】,此时锁升级

如何锁升级为轻量级锁:当线程B想访问synchronized同步代码块时,会检查synchronized关键字对应的锁对象的对象头中,Markword中线程ID是否为线程B的ID,若不是则B再检查锁对象头中记录的线程A是否还存活,不存活则直接把锁对象先置为无锁状态,再获取锁使其变为偏向锁;若存活则先暂停线程A,撤销偏向锁,再把【锁=锁对象】升级为轻量级锁,然后B线程自旋(不断循环调用cas获取锁,自旋会消耗cpu使得cpu空转,所以自旋有次数限制)

轻量级锁

如何升级为重量级锁:B线程在访问同步代码块时发现A线程正在占用锁对象,故把【锁=锁对象】升级为轻量级锁,然后B自旋了,这时又有C线程来,此时轻量级锁升级为重量级锁,同时除了得到锁的那个线程,其他线程均会被阻塞

synchronized由无锁状态膨胀为重量锁的特点
  • jvm默认延迟4s后才开启偏向锁,在这4s期间的(锁=锁对象)又叫匿名偏向锁,4s后才记录得到锁的线程,可通过【-XX:BiasedLockingStartUpDelay=0】取消延时,可通过【-XX:-UseBiasedLocking = false】设置不要偏向锁
  • 除了偏向锁可以降为无锁状态,其他锁只能升级,不能降级
  • 偏向锁和轻量级锁在用户态维护,而重量级锁在内核态维护

OK,如果文章哪里有错误或不足,欢迎各位留言。

创作不易,各位的「三连」是二少创作的最大动力!我们下期见!

这篇关于synchronized锁及其锁升级的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!