十二、偏向锁、轻量级锁、重量级锁,锁的膨胀过程

1、对象的状态有几种:

无锁、偏向锁、轻量级锁、重量级锁、GC标记,共5个状态
在这里插入图片描述

2、锁的膨胀过程

  • 无锁:程序多线程执行过程中没有去执行synchronized修饰区域或者方法。
  • 偏向锁:发生在程序单线程执行过程中,由始至终只有一个线程去执行过synchronized修饰区域或者方法,由于是由始至终只有一个线程去执行所以没有发生竞争、等待、抢锁的情况,它不会调用操作系统的函数去实现同步。
  • 轻量级锁:发生在程序多线程执行过程中有去执行synchronized修饰区域或者方法,且没有发生竞争、等待、抢锁的情况或者发生了竞争、等待、抢锁但是竞争、等待和抢锁的时间没有超过一个JVM设定的自旋时间或者次数的时候,它是在虚拟机内部去实现的同步,不会调用操作系统的函数去实现同步。
  • 重量级锁:发生在程序多线程执行过程中有去执行synchronized修饰区域或者方法,且发生了竞争、等待、抢锁且竞争、等待和抢锁的时间已经超过一个JVM设定的自旋时间或者次数的时候,它会调用操作系统的函数去实现同步(调用操作系统实现同步,需要的步骤很多,导致性能相对于其它锁实现同步的方式就很低)。

3、锁的标识码

  • 无 锁 001
  • 偏 向 锁 101
  • 轻量级锁 000
  • 重量级锁 010

示例如下:在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过 -XX:BiasedLockingStartupDelay=0 可以设置延迟开启偏向锁的时间

4、几种锁的效率对比

  • 无 锁: 耗时61毫秒
  • 偏 向 锁: 耗时2051毫秒
  • 轻量级锁: 耗时18302毫秒
  • 重量级锁: 耗时43470毫秒

下面是无锁、偏向锁、轻量级锁 耗时测试代码

package day07.part1;

/**
 * synchronized关键字的底层原理
 *
 * 偏向锁和轻量级锁对比
 * -XX:BiasedLockingStartupDelay=0 立即开启偏向锁
 * -XX:BiasedLockingStartupDelay=30000 30秒后再开启偏向锁 那30秒以前开启的是轻量级锁
 *
 * 无锁:不设置偏向锁,不加synchronized关键字             用时是:61毫秒
 * 偏向锁:设置偏向锁,加synchronized关键字 即使没有线程
 *        安全问题需要同步,那么加上了synchronized也就
 *        有了同步的嫌疑,所以jvm还是给它加了一把偏向锁      用时是:2051毫秒
 *
 * 轻量级锁:不设置偏向锁,加synchronized关键字           用时是:18302毫秒
 * 轻量级锁:设置偏向锁30秒后开启,加synchronized关键字    用时是:17702毫秒
 *
 *
 * @author xzq
 */
public class SynchronizedBottomTest07 {

    public static void main(String[] args) throws InterruptedException {
        Test test=new Test();

        long beforeTime = System.currentTimeMillis();
        //执行10亿次
        for(int i=0;i<1000000000;i++){
            test.testIncreament();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用时是:"+(endTime-beforeTime)+"毫秒");
    }

    static  class  Test{

        private int l=0;

        public synchronized void testIncreament(){
            l++;
        }
    }
}


重量级锁耗时示例
例子中2个线程竞争 直接上来就加了重量级锁。

package day07.part1;

import java.util.concurrent.CountDownLatch;

/**
 * synchronized关键字的底层原理
 *
 * 轻量级锁和重量级锁对比
 *
 * 用时是:45035毫秒
 * -XX:BiasedLockingStartupDelay=0
 * 配置-XX:BiasedLockingStartupDelay=0 后 耗时依然有 用时是:44878毫秒
 * 说明2个线程竞争 直接上来就加了重量级锁 而不会上偏向锁
 * @author xzq
 */
public class SynchronizedBottomTest08 {

    private static CountDownLatch cdLatch=new CountDownLatch(1000000000);

    public static void main(String[] args) throws InterruptedException {

        final Test test=new Test();

        long beforeTime = System.currentTimeMillis();

        //创建两个线程去执行,这样就产生了竞争就是重量级锁
        for(int i=0;i<2;i++){
            new Thread(){

                @Override
                public void run() {
                    //执行10亿次
                    while(cdLatch.getCount()>0){
                        test.testIncreament();
                    }
                }

            }.start();
        }
        cdLatch.await();
        long endTime = System.currentTimeMillis();
        System.out.println("用时是:"+(endTime-beforeTime)+"毫秒");

    }

    static  class  Test{

        private int l=0;

        public synchronized void testIncreament(){
            l++;
            cdLatch.countDown();
        }
    }
}


在这里插入图片描述

5、锁的膨胀过程

代码示例

package day07.part1;

import org.openjdk.jol.info.ClassLayout;

/**
 * synchronized关键字的底层原理
 *
 * 演示整个锁的膨胀过程和成为重量级锁后
 * 所有线程退出同步代码区域后,MarkWord是什么锁状态 这里测试结果为无锁状态
 * -XX:BiasedLockingStartupDelay=0
 * 无锁 001
 * 偏向锁  101
 * 轻量级锁 000
 * 重量级锁 010
 *
 * @author xzq
 */
public class SynchronizedBottomTest09 {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        mainThread.setName("主线程:");
        final Test testLock=new Test();
        System.out.println("--------------------------所有线程加锁前------------------------------------");
        System.out.println(ClassLayout.parseInstance(testLock).toPrintable());//无锁
        Thread t=new Thread("子线程:"){
            @Override
            public void run() {
                String threadName = Thread.currentThread().getName();
                synchronized (testLock) {
                    System.out.println(threadName+"---------------------------------加锁后----------------------------");
                    System.out.println(ClassLayout.parseInstance(testLock).toPrintable());//轻量级锁
                    //休眠3秒
                    try {Thread.sleep(3_000);} catch (InterruptedException e) {}
                }
                System.out.println(threadName+"---------------------------------释放了锁!----------------------------");
            }
        };
        t.start();
        Thread.sleep(1000);
        //让主线程和子线程产生竞争、抢锁
        synchronized (testLock) {
            System.out.println("------------------------------主线程和子线程发生竞争抢锁-------------------------------");
            System.out.println(ClassLayout.parseInstance(testLock).toPrintable());//重量级锁
        }
        Thread.sleep(5_000);
        System.out.println("---------------------------------主线程和子线程都释放了锁!----------------------------");
        System.out.println(ClassLayout.parseInstance(testLock).toPrintable());//重量级锁
    }
    static class Test{
    }
}


测试结果如下:

/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=55003:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/lib/tools.jar:/Users/xuzhiqiang/ideaProjects/SpringBoot/synchronize/target/classes:/Users/xuzhiqiang/.m2/repository/org/openjdk/jol/jol-core/0.9/jol-core-0.9.jar day07.part1.SynchronizedBottomTest09
--------------------------所有线程加锁前------------------------------------
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
day07.part1.SynchronizedBottomTest09$Test object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

子线程:---------------------------------加锁后----------------------------
day07.part1.SynchronizedBottomTest09$Test object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           a8 19 ea 03 (10101000 00011001 11101010 00000011) (65673640)
      4     4        (object header)                           00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
      8     4        (object header)                           a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

------------------------------主线程和子线程发生竞争抢锁-------------------------------
子线程:---------------------------------释放了锁!----------------------------
day07.part1.SynchronizedBottomTest09$Test object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           4a 7f 80 ed (01001010 01111111 10000000 11101101) (-310345910)
      4     4        (object header)                           9e 7f 00 00 (10011110 01111111 00000000 00000000) (32670)
      8     4        (object header)                           a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

---------------------------------主线程和子线程都释放了锁!----------------------------
day07.part1.SynchronizedBottomTest09$Test object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)                           a0 c1 00 f8 (10100000 11000001 00000000 11111000) (-134168160)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
轻量级重量级偏向锁是Java中的三种不同的机制。轻量级是一种乐观,用于在多线程环境下提高并发性能。当竞争不激烈时,轻量级使用CAS(Compare and Swap)操作来获取,避免了线程阻塞,提升了性能。然而,如果竞争激烈,轻量级膨胀重量级偏向锁是在没有竞争的情况下,为了进一步提高性能而引入的机制。偏向锁允许第一个获得的线程在接下来的执行中,无需再进行同步操作,从而减少了不必要的竞争。当有其他线程试图获取偏向锁时,偏向锁会升级为轻量级重量级重量级是一种传统的互斥,它使用操作系统原语(例如互斥量)来实现线程阻塞和唤醒,确保同一时间只有一个线程可以访问被定的资源。重量级适用于竞争激烈的场景,但由于涉及到内核态和用户态之间的切换,会带来较大的性能开销。 总结起来,轻量级偏向锁都是为了提高并发性能而引入的机制,轻量级适用于竞争不激烈的场景,而偏向锁适用于没有竞争的情况下。重量级适用于竞争激烈的场景,但会带来较大的性能开销。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [浅谈偏向锁轻量级重量级](https://blog.csdn.net/yaojiqic/article/details/124619021)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Java中的偏向锁轻量级重量级解析](https://blog.csdn.net/lengxiao1993/article/details/81568130)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java的升级策略 偏向锁 轻量级 重量级](https://download.csdn.net/download/weixin_38512659/12749004)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值