栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

synchronized底层原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

synchronized底层原理

一探究竟:反编译

三种使用场景,示例代码;

public class SynchronizePrincipe {

    public synchronized static void fun1(){}
    public synchronized void fun2(){}
    public void fun3() {
        synchronized (this){}
    }
}

通过javap -c -v命令反编译后(部分代码);

 public static synchronized void fun1();
    descriptor: ()V
    // 看这里
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRonIZED

  public synchronized void fun2();
    descriptor: ()V
    // 看这里
    flags: ACC_PUBLIC, ACC_SYNCHRonIZED

  public void fun3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         // 看这里
         3: monitorenter
         4: aload_1
         // 看这里
         5: monitorexit
         6: goto          14
         9: astore_2
        10: aload_1
         // 看这里
        11: monitorexit

修饰方法:ACC_SYNCHRONIZED标识,会隐式调用到下面两个方法;修饰代码块:一个monitorenter,两个monitorexit,避免异常未释放锁;

总结:sychronized本质就是对monitor的争夺,在持有重量级锁的对象头中,存储了monitor的指针。

基础知识:对象结构

Java对象由三个部分组成;

    对象头:对象年龄,锁标志,Class类型指针和数组长度(可选);实例数据:真正存储的有效数据,例如当前的成员变量,包括父类;对齐填充:HotSpot VM规定对象起始地址为8字节的整数倍,不够则需要填充;
Mark Word

重中之重:对象锁

JDK 1.6 增加的锁优化流程,之前只有重量级锁。

锁类型

non-biasable 无锁且不可偏向biasable 无锁可偏向biased 偏向锁thin lock 轻量级锁fat lock 重量级锁 rebias & revoke

bulk rebias(批量重偏向):如果已经偏向t1线程的对象,在t2线程申请锁时撤销偏向后升级为轻量级锁的对象数量达到一定值(20),后续的申请会批量重偏向到t2线程;bulk revoke(批量撤销):在单位时间(25s)内某种Class的对象撤销偏向的次数达到一定值(40),JVM认定该Class竞争激烈,撤销所有关联对象的偏向锁,且新实例也是不可偏向的; 对象初始化

申请加锁

证据第一:动手试试 JVM参数
-XX:+UseBiasedLocking 启用偏向锁,默认启用
-XX:+PrintFlagsFinal 打印JVM所有参数
-XX:BiasedLockingStartupDelay=4000 偏向锁启用延迟时间,默认4秒
-XX:BiasedLockingBulkRebiasThreshold=20 批量重偏向阈值,默认20
-XX:BiasedLockingBulkRevokeThreshold=40 批量撤销阈值,默认40
-XX:BiasedLockingDecayTime=25000
添加依赖

    org.openjdk.jol
    jol-core
    0.16

统一打印对象头方法;

public static void print(Object flag, Object object) {
    String str = ClassLayout.parseInstance(object).toPrintable();
    System.out.println(flag + ".......................................");
    System.out.println(str);
}
锁升级
public static void main(String[] args) {
    Object init = new Object();
    // non-biasable 不可偏向
    print("init before", init);
    synchronized (init) {
        // thin lock 轻量级锁
        print("init sync", init);
    }
    sleep(4000);
    Object object = new Object();
    // biasable 可偏向模式,默认4S后开启偏向模式
    print("object before", object);
    synchronized (object) {
        // biased 持有偏向锁
        print("object sync", object);
    }
    // biased 偏向锁不会被释放
    print("object after", object);

    Thread t1 = new Thread(() -> {
        synchronized (object) {
            // thin lock 持有轻量级锁,不同线程请求
            print("[t1]object sync", object);
        }
        // non-biasable 不可偏向模式
        print("[t1]object after", object);
    });
    t1.start();
    sleep(100);
    Thread t2 = new Thread(() -> {
        synchronized (object) {
            // thin lock 持有轻量级锁,不同线程请求
            print("[t2]object sync", object);
            sleep(1000);
            // fat lock 重量级锁,下面加锁失败导致
            print("[t2]object sync sleep", object);
        }
    });
    t2.start();
    sleep(500);
    synchronized (object) {
        // fat lock 重量级锁
        print("[main]object sync", object);
    }
    // fat lock 重量级锁不会撤销,线程结束变为不可偏向模式
    print("[main]object after", object);
}
批量重偏向&批量撤销
public static void main(String[] args) throws InterruptedException {
    print("oldPrincipe", new SynchronizedPrincipe());
    int loop = 39;
    List list = new ArrayList<>();
    for (int i = 0; i < loop; i++) {
        SynchronizedPrincipe principe = new SynchronizedPrincipe();
        list.add(principe);
    }
    for (int thread = 1; thread <= 3; thread++) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < list.size(); i++) {
                print(i + 1, list.get(i));
                synchronized (list.get(i)) {
                    // 19: thin lock
                    // 20: biased (Rebias)
                    print(i + 1, list.get(i));
                }
                print(i + 1, list.get(i));
            }
        });
        t1.start();
        sleep(1000);
    }
    SynchronizedPrincipe newPrincipe = new SynchronizedPrincipe();
    // non-biasable (Revoke)
    print("newPrincipe", newPrincipe);
}
参考

关于 Synchronized 的一个点,网上99%的文章都错了并发系列三:证明分代年龄、无锁、偏向锁、轻量锁、重(chong)偏向、重(chong)轻量、重量锁

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/754606.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号