深度了解各种锁(更新中)

解决线程安全都有哪几种方式?

1. 锁(悲观锁,乐观锁)

2.原子类Atomic(CAS比较并赋值,防止线程睡觉,从用户态转换成内核态,自旋重试10次)

3.Threadlocal

悲观锁 

synchronized介绍

1. synchronized是基于JVM实现的,是java的一个关键字,可以修饰方法、对象、代码块,但是锁得都是对象;

2. 底层是mutix互斥变量;

3. 加锁:monitor enter 释放锁:monitor exit;

4.不可以手动加锁释放锁;

5.1.6之前是一个重量型锁,效率慢,因为线程一旦抢不到锁,会阻塞状态(睡觉),并且会有死锁的情况。1.6之后进行了优化,锁升级

6.是一个非公平锁并且可重入,不能指定等待时间

synchronized底层实现

java中每一个new的对象中,都有一一绑定的monitor对象(c++实现),由他来操作synchronized底层的mutex互斥变量达到锁的效果

synchronized 1.6锁优化(升级,消除,粗化)

一旦线程抢不到锁,那就会从用户态变成内核态,还要去重新抢占cpu资源去拿锁,很耗费性能,所以才要进行优化

一 锁升级

当一个对象只有在无锁的时候,对象头markdown才会存储hashcode,如果这个时候调用他的hashcode方法会从无锁直接升级成重量级锁,因为没有地方存threadId了,也就是没有偏向锁了

对象头markdown中的分代年龄 大小为4bit位 最大是15,再大就放不下了,所以垃圾回收,青年代到老年代要经过15次才到老年代

1. 无锁

没有任何锁竞争的场景(可以看下面的锁消除的代码例子)

2.偏向锁

只有单线程执行任务(比如单线程多次调用synchronized同步代码块),对象头中的markdown会记录拿到锁的线程id,如果下次又来获取锁的话会直接获取到

3.轻量锁

有两个或两线程执行任务(并发不高),可能第一个线程执行个几毫秒后就释放锁了(稍微自旋一下就抢到锁了)

4.重量锁

有多个线程在执行任务(并发高),并且还很耗时很久不释放锁,CAS就吃不消了,那其他没抢到锁的线程就直接睡觉去了

二 锁粗化

java代码中,有连续多个synchronized代码块,合并成一个大的代码块,这样就不用多次上锁解锁

三 锁消除

锁消除,虽然写了synchronized代码块,但是根本没有用到锁,都没有锁竞争,所以就直接消除了

锁的升级流程:(了解即可,面试加分项)

首先当单线程执行任务的时候,对象的markdown中会记录当前持有锁的线程id,ThreadId

当再有一个线程要执行任务的时候(他会等到全局安全点 safe point 再去执行)

他会判断第一个线程是否还在存活或者是否还持有锁

如果不存活了死了,他会拿到锁(这时候还是偏向锁)

如果还在存活,并且代码块已经执行完毕了,那这时候也会拿到锁(还是偏向锁)

如果还在存活,并且还在执行代码块,这时候就不满足便向锁的概念了(就不是单线程了),就要升级成轻量级锁,需要做3步操作

1. 将第一个对象中的markdown搬到 线程栈  lock recod 空间中

2.指针指向lock recod 空间(不指向就找不到markdown了,并且也是为了节省空间,64位操作系统中一个指针就有64bit)

3.再cas一下

如果cas失败了,那就意味了出现了比较明显的竞争了,那就要升级成重量级锁

对象中的markdown会复制一份到monitor对象中,用指针和monitor对象关联上,用monitor对象来操作synchronized中的mutex互斥变量来实现重量锁

ReentrantLock介绍

1.基于JDK实现的;

2. 可以手动加锁和释放锁(lock());

3.可以设置等待时间;

4.可以是非公平也可以是公平(可以设置),也是可重入锁;

5.1.6之前性能是比synchronized高,1.6之后由于synchronized进行了优化,他俩的性能差不多

ReentrantLock的底层实现

原理其实就是利用了CAS,修改变量state+1,如果成功了就加到了锁,如果不成功AQS自旋重试一次,他之前比synchronized性能好就是因为这个CAS的操作,尽可能不让线程切换状态,会把自己包装成一个node节点,如果是头节点的话,会CAS一下抢一下锁,但是synchronized(1.6之前)是其他线程抢不到锁会去睡觉再唤醒,性能很低。

乐观锁

CAS算是乐观锁(比较并赋值),他不是真正的锁,是逻辑锁,也能达到锁的效果,但是不适用与并发高的情况,cas在并发高的情况,由于自旋空转时间久了也很浪费cpu的性能

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值