zoukankan      html  css  js  c++  java
  • Synchronized实现原理

    Synchronized的四种锁状态:无锁状态,偏向锁,轻量级锁,重量级锁

    轻量级级锁的实现原理

    轻量级锁的使用场景:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的,也就是说没有竞争,那么完全可以用轻量级锁来优化

    假设有两个方法同步块,利用同一个对象加锁

    static final Object obj = new Object();
    public static void method1(){
        synchronized(obj){
            //同步块A
            method2();
        }
    }
    
    public static void method2(){
        synchronized(obj){
            //同步块B
        }
    }
    • 创建锁记录(Lock Record)对象,每个线程的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的MarkWord

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

    •  如果cas替换成功,对象头中存储了锁记录地址和状态00,表示由该线程给对象加锁,这时图示如下

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

    • 当退出synchronized代码块(解锁)的时候,如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一

    • 当推出synchronized代码块(解锁)时,锁记录的值不为null,那么将使用cas将Mark Word的值恢复给对象头
    1. 成功,则解锁成功
    2. 失败,说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级锁解锁流程

    重量级锁的实现原理

    给一个对象(obj)加锁,会在操作系统层面获取一个监视器Monitor,有时候也叫管程)对象,对象obj的Markword会指向该Monitor对象,原本Markword中存放的分代年龄等信息会存放在Monitor对象里。Monitor里的Owner指向持有该对象obj的锁的线程Thread_1。当其它线程Thread_2, Thread_3试图获取对象obj的锁时,发现Owner已经指向了Thread_1,也就是Thread_1已经获取该对象的锁时后,那么Monitor的EntryList就会将Thread_2,Thread_3放到EntryList里面,等到Thread_1释放锁后,再从EntryList里取出一个线程,将Monitor里的Owner指向该进程。每个对象都有自己的Monitor

     图中Thread_1释放锁,Thread_2获得obj的锁,

    需要注意的是:只有在用synchronized关键字修饰后,才会有上述对象markword指向Monitor,否则的话,是不会去向操作系统申请这一Monitor对象的。而且,必须是重量级锁才会申请这个Monitor

  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/Chsy/p/12712625.html
Copyright © 2011-2022 走看看