Java并发(四)synchronized关键字(1)基本原理

一.用法

就记住一点:synchronized修饰非静态方法时,锁是this,即当前的实例对象。synchronized修饰静态方法时,锁是类对象。

二.原理

2.1 预备知识(对象头)

  1. 在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。
  2. 对象头又分为Mark Word 和 Klass Word。Mark Word用于存储对象自身的运行时数据,如:哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID等。Klass Word为类型指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例。如图1所示:
    在这里插入图片描述
    图1

2.2 Monitor

  1. Monitor被翻译为监视器或管程,是操作系统提供的对象。每个Java对象都可以关联一个Monitor对象,如果使用synchronized给对象A上锁(重量级锁)之后,该对象A的对象头的Mark Word中的相应部分就被设置指向Monitor对象的指针,Mark Word中的锁标志位置为10。如图2所示:
    在这里插入图片描述
    图2
  2. Monitor中分三个结构:Owner、EntryList、WaitSet。
    (1)Owner:当某一线程Thread-2执行synchronized(obj)并成功加锁,该obj关联的Monitor的Owner就置为Thread-2。
    (2)EntryList:用于存放那些等待Thread-2释放obj的线程,这些线程处于BLOCKED状态。
    (3)WaitSet:用于存放那些之前获得过锁,但条件不满足而进入WAITING状态的线程。具体见后面的wait-notify。
    具体见图3:
    在这里插入图片描述
    图3

2.3 Monitor-字节码角度

代码如图4所示:
在这里插入图片描述
图4

该段代码对应的字节码指令如图5所示:
在这里插入图片描述
图5
从图5中看出,15行和21行都是monitorexit指令,但为什么会有两次monitorexit指令呢?因为当顺利执行完16行时,锁已经释放了,就直接跳到24行,方法就正常返回了。但如果6到16行发生了异常,锁有可能没释放,就需要跳到19行(见图5异常表),然后往下执行,直到21行正确执行,这样能够保证锁顺利释放。

三.优化

关于偏向锁、轻量级锁相关,看 并发编程_原理.pdf 17~33页的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值