无痕
召唤看板娘

一.锁升级理论.

在synchronized锁升级过程中涉及到以下几种锁.先说一下这几种锁是什么意思.

偏向锁:只有一个线程争抢锁资源的时候.将线程拥有者标识为当前线程. 轻量级锁(自旋锁):一个或多个线程通过CAS去争抢锁,如果抢不到则一直自旋. 重量级锁:多个线程争抢锁,向内核申请锁资源,将未争抢成功的锁放到队列中直接阻塞.

为什么要有锁的升级过程?

  在最开始的时候,其实就是无锁直接到重量级锁,但是重量级锁需要向内核申请额外的锁资源,这就涉及到用户态和内核态的转换,比较浪费资源,而且大多数情况下,其实还是一个线程去争抢锁,完全不需要重量级锁.

锁的具体升级过程(通常情况下):

1.当只有一个线程去争抢锁的时候,会先使用偏向锁,就是给一个标识,说明现在这个锁被线程a占有. 2.后来又来了线程b,线程c,说凭什么你占有锁,需要公平的竞争,于是将标识去掉,也就是撤销偏向锁,升级为轻量级锁,三个线程通过CAS进行锁的争抢(其实这个抢锁过程还是偏向于原来的持有偏向锁的线程). 3.现在线程a占有了锁,线程b,线程c一直在循环尝试获取锁,后来又来了十个线程,一直在自旋,那这样等着也是干耗费CPU资源,所以就将锁升级为重量级锁,向内核申请资源,直接将等待的线程进行阻塞.

什么情况下偏向锁才会升级为轻量级锁,什么时候轻量级锁才会升级为重量级锁?

只有一个线程的时候就是偏向锁(当偏向锁开启的时候,偏向锁默认开启),当争抢的线程超过一个,升级为轻量级锁.

当自旋的线程循环超过10次,或者线程等待的数量超过cpu的1/2,升级为重量级锁.其实轻量级锁就适用于那种执行任务很短的线程,可能通过一两次自旋,就能够获取到锁.

开启偏向锁一定比轻量级锁高效吗?

  不一定,比如在一开始已经知道某个资源就需要被多个线程争抢,此时就不需要开启偏向锁,因为偏向锁给了标识之后,还需要取消这个标识,重新抢锁,比如在JVM中,偏向锁默认是延迟4秒才开始的,因为JVM在启动的时候需要多个线程竞争资源,并且这个都是一开始知道的.

重量级锁 对应 10 轻量级锁 对应 00 无锁和偏向锁都对应01,这个时候需要倒数第三个字节加以区分, 即 无锁 对应 001, 偏向锁 对应 101

package com.example.demo.wuhen;

import org.openjdk.jol.info.ClassLayout;

public class Synchronizeds {
    static  Object obj=new Object();

    static class LockThread implements  Runnable{

        @Override
        public void run() {
            synchronized (obj){

                String test="";

                for (int i = 0; i < 1000; i++) {
                    test+="2";
                }
            }
        }
    }

public static void main(String[] args) {


        new Thread(new LockThread()).start();
        System.out.println("=============偏向锁============");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());


        new Thread(new LockThread()).start();
        System.out.println("=============轻量级锁============");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());


        for (int i = 0; i < 20; i++) {

            new Thread(new LockThread()).start();
        }

        System.out.println("=============重量级锁============");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
    }

}

控制台输出
=============偏向锁============
# WARNING: Unable to get Instrumentation. Dynamic Attach failed. You may add this JAR as -javaagent manually, or supply -Djdk.attach.allowAttachSelf
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           05 e0 20 c5 (00000101 11100000 00100000 11000101) (-987701243)
      4     4        (object header)                           d3 02 00 00 (11010011 00000010 00000000 00000000) (723)
      8     4        (object header)                           00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

=============轻量级锁============
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           28 f3 af 92 (00101000 11110011 10101111 10010010) (-1833962712)
      4     4        (object header)                           f0 00 00 00 (11110000 00000000 00000000 00000000) (240)
      8     4        (object header)                           00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

=============重量级锁============
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
      0     4        (object header)                           02 70 be c4 (00000010 01110000 10111110 11000100) (-994152446)
      4     4        (object header)                           d3 02 00 00 (11010011 00000010 00000000 00000000) (723)
      8     4        (object header)                           00 10 00 00 (00000000 00010000 00000000 00000000) (4096)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
end

评论

asd
asd
asd  @ asd
aasd
wuhen  @ asd
112313
wuhen  @ wuhen
wasdaasd
wuhen  @ wuhen
留言