java并发实现_3.java并发机制及实现原理(2)

说到java并发编程,就不得不说synchronized关键字,很多人称之为“重量级锁”,其实JAVASE 1.6对ynchronized进行的各种优化,synchronized并不会显得那么重了

本章要点

1.锁升级

2.synchronized

java中任何一个对象都可以作为锁

synchronized修饰实例方法,锁是当前实例对象

synchronized修饰静态方法,锁是当前类的class对象

synchronized修饰代码块,锁是括号里面的对象

3.1锁升级

锁级别分为:无锁-->偏向锁-->轻量级锁-->重量级锁(真正意义上的加锁)

偏向锁(CAS操作):大多数时候是不存在锁竞争的,通常是一个线程多次获得同一个锁,因此如果每次都要竞争锁会增大很多没有必要付出的代价,为了降低获取锁的代价,才引入的偏向锁。此时会在java对象头和栈帧中记录偏向的锁的threadID。

轻量级锁(自旋锁):考虑的是竞争锁对象的线程不多,而且线程持有锁的时间也不长的情景(两个线程交替访问)。因为阻塞线程需要CPU从用户态转到内核态,代价较大,如果刚刚阻塞不久这个锁就被释放了,那这个代价就有点得不偿失了,因此这个时候就干脆不阻塞这个线程,让它自旋这等待锁释放。

重量级锁(基于ObjectMonitor):多个线程竞争资源,竞争激烈,在操作一定次数的自旋锁(cas操作)后,还没有获得轻量级锁,锁膨胀为重量级锁,没有获取锁的线程会被阻塞。

偏向锁:

16367b23486c

偏向锁.png

轻量级锁:

16367b23486c

轻量级锁.png

3.2 synchronized 基本原理

synchronized是基于ObjectMonitor实现的,ObjectMonitor中有几个关键属性:

_owner:指向持有ObjectMonitor对象的线程

_WaitSet:存放处于wait状态的线程队列

_EntryList:存放处于等待锁block状态的线程队列

_recursions:锁的重入次数

_count:用来记录该线程获取锁的次数

1.只有_EntryList线列才有权利争抢锁资源 2.调研notify或者notifyAll方法,其实就是将线程从_WaitSet移到_EntryList中,然后让其去争抢锁资源

总之,被synchronized修饰的代码,在被编译器编译后在被修饰的代码前后加上了一组字节指令。代码开始位置加上monitorenter,在代码结束位置加入monitorexit,这两个字节码指令配合完成了synchronized关键字修饰代码的互斥访问。

当执行monitorenter时,若对象未被锁定时,或者当前线程已经拥有了此对象的monitor锁,则锁计数器+1,该线程获取该对象锁。

当执行monitorexit时,锁计数器-1,当计数器为0时,此对象锁就被释放了。那么其他阻塞的线程则可以请求获取该monitor锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值