JUC并发 4.26-4.47

26

Monitor

后面的四字节是一个指针,指向了该对象从属的class,不如说Student Tom = new Student();

那么这个Klass Word指向的就是Student.class(类对象)

Mark Word里面存储了该对象的状态

注意到,Integer比int至少要多存储一个Object Header的8字节,相当于三倍大小

27 Monitor: 监视器,管程

每一个java对象都可以关联一个管程!

调用synchronized给对象上锁,对象的mark word就会被设置指向monitor的指针

MarkWord里面记录了Monitor的指针

被加上synchronized,mark word的01改成10,hashcode,age都不要,改成一个指向heavy weight monitor的指针(30bit)

来了一个thread,当然就成为了owner了!

又来了两个,拿不到锁就在entryList那里链表等着

线程2执行完了之后,叫醒1跟3,1和3都有可能获取得到(非公平)

另外的一个对象会有一个不一样的monitor

28 字节码monitor

上面这个是什么意思呢?

29 synchronized优化

如果每次进入synchronized都要获取锁,对性能有很大影响

java6:轻量级锁,偏向锁!

故事角色
老王 - JVM
小南 - 线程
小女 - 线程
房间 - 对象
房间门上 - 防盗锁 - Monitor
房间门上 - 小南书包 - 轻量级锁
房间门上 - 刻上小南大名 - 偏向锁
批量重刻名 - 一个类的偏向锁撤销到达 20 阈值
不能刻名字 - 批量撤销该类对象的偏向锁,设置该类不可偏向

小南要使用房间保证计算不被其它人干扰(原子性),最初,他用的是防盗锁,当上下文切换时,锁住门。这样,即使他离开了,别人也进不了门,他的工作就是安全的。


但是,很多情况下没人跟他来竞争房间的使用权。小女是要用房间,但使用的时间上是错开的,小南白天用,小女晚上用。每次上锁太麻烦了,有没有更简单的办法呢?

根本没啥必要加锁,因为时间上的错开,两个线程并不会冲突

小南和小女商量了一下,约定不锁门了,而是谁用房间,谁把自己的书包挂在门口,但他们的书包样式都一样,因此每次进门前得翻翻书包,看课本是谁的,如果是自己的,那么就可以进门,这样省的上锁解锁了。万一书包不是自己的,那么就在门外等,并通知对方下次用锁门的方式。

轻量级锁,翻背包,如果冲突过一次,就升级为锁门的重量级锁

后来,小女回老家了,很长一段时间都不会用这个房间。小南每次还是挂书包,翻书包,虽然比锁门省事了,但仍然觉得麻烦。
于是,小南干脆在门上刻上了自己的名字:【小南专属房间,其它人勿用】,下次来用房间时,只要名字还在,那么说明没人打扰,还是可以安全地使用房间。如果这期间有其它人要用这个房间,那么由使用者将小南刻的名字擦掉,升级为挂书包的方式。 

偏向锁,专属线程使用,假定只有他一个用。冲突了就变成轻量级锁

同学们都放假回老家了,小南就膨胀了,在 20 个房间刻上了自己的名字,想进哪个进哪个。后来他自己放假回老家了,这时小女回来了(她也要用这些房间),结果就是得一个个地擦掉小南刻的名字,升级为挂书包的方式。老王觉得这成本有点高,提出了一种批量重刻名的方法,他让小女不用挂书包了,可以直接在门上刻上自己的名字后来,刻名的现象越来越频繁,老王受不了了:算了,这些房间都不能刻名了,只能挂书包。

 阈值分别是20和40,20的时候批量重刻名,40的时候批量撤销该类对象的偏向锁,设置该类不可偏向

30

让锁记录中 Object reference 指向锁对象,并尝试用 cas 替换 Object 的 Mark Word,将 Mark Word 的值存入锁记录

如果 cas 失败,有两种情况
如果是其它线程已经持有了该 Object 的轻量级锁,这时表明有竞争,进入锁膨胀过程
如果是自己执行了 synchronized 锁重入,那么再添加一条 Lock Record 作为重入的计数

31 锁膨胀

32 自旋优化

重量级锁竞争,当前线程自旋成功(退出了同步块释放了锁),本线程就不用阻塞

自旋在多核cpu才有意义?

33 偏向锁

同一个方法重复调用的话,轻量锁多次进入,cas检查操作,十分繁琐

所以我们就有偏向锁,直接把自己刻在对象上

第一次的时候,cas将线程ID设置到对象的Mark Word头,之后发现这个线程ID在这个上面,就说明没有竞争

34 偏向锁状态

默认开启了偏向锁

markword后三位就是101

调用完hashcode,直接就不能用偏向锁了,没地方存储了

轻量级由栈帧来存,重量级锁由monitor存

35 偏向锁撤销

000……000101表示处于可以加偏向锁的状态

wait notify只有重量级锁用,一旦用了也是不能偏向了

36 批量重偏向

对象被多个线程访问,没有竞争,还是可以改成另外一个thread的id的

正常情况:

t1给obj1写入自己的id

t2去访问obj1,修改obj1为轻量级锁

重复上面的20次,jvm就会发现不对劲,然后开启批量重偏向,剩下所有的锁都是重偏向

37 批量撤销

40次之后,直接就给整个类的锁,批量撤销偏向锁,都别用偏向锁了,再创建也不能了,变成001结尾

38 锁消除

锁消除优化,jit自动将没有用的锁给干掉,这样性能就又提升了

39

40

 

状态都是waiting,都被挂起了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值