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

  • 相关阅读:
    DISTINCT 方法用于返回唯一不同的值 。
    UNION操作用于合并两个或多个 SELECT 语句的结果集。
    JOIN方法也是连贯操作方法之一
    HAVING方法也是连贯操作之一
    GROUP方法也是连贯操作方法之一
    page方法也是模型的连贯操作方法之一
    limit方法也是模型类的连贯操作方法之一
    order方法属于模型的连贯操作方法之一
    field方法属于模型的连贯操作方法之一
    data方法也是模型类的连贯操作方法之一,
  • 原文地址:https://www.cnblogs.com/Chsy/p/12712625.html
Copyright © 2011-2022 走看看