synchronized学习(一): synchronized的执行过程

 JDK1.6中为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁。

 synchronized的执行过程: 

1. 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁

2. 如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1

3. 如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。

4. 当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁

5. 如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。

6. 如果自旋成功则依然处于轻量级状态。

7. 如果自旋失败,则升级为重量级锁。

加锁 解锁 优点 缺点 适用场景
偏向锁

 初始:CAS竞争锁,在对象头和栈帧的锁记录里存储线程ID,并置偏向标志位1

非初始:检查Mark Word是否存放当前线程ID

扫描二维码关注公众号,回复: 3549759 查看本文章

其他线程:产生竞争,引起偏向锁释放

 条件:其他线程尝试竞争偏向锁

等待全局安全点,暂停拥有偏向锁的线程;如果线程不处于活动状态则设置为无锁状态;否则,将栈中的锁记录和对象头的Mark Word:重新偏向其他线程 or 恢复到无锁 or 标记对象不适合作为偏向锁。

疑问:1)为什么要在全局安全点?

2)继续偏向锁 or 升级轻量锁的时机是什么?

 省掉CAS  锁竞争时,带来额外的锁撤销  只有一个线程访问同步块
轻量锁

1)将Mark Word复制到栈锁记录,Displaced Mark Word;

2)CAS将MW替换为锁记录的指针;

3)失败则自旋;

4)自旋超过一定限制则修改MW为重量锁(指向重量锁-互斥量的指针),并阻塞

1)CAS将DMW替换回对象头;

2)失败则说明已经变为重量锁

 不会阻塞和唤醒,提高响应速度 自旋消耗CPU 

追求响应时间

同步块执行速度非常快 

重量锁  同轻量锁,但获取失败时直接阻塞

1)释放锁;

2)唤醒等待的线程;

 不自旋消耗CPU 线程调度 

追求吞吐量

同步块执行时间较长 

 

猜你喜欢

转载自www.cnblogs.com/cheng18/p/9779584.html