synchronized底层原理

Posted wangymd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized底层原理相关的知识,希望对你有一定的参考价值。

1、整理的思维导图

技术图片

 2、字节码分析

 

package com.javabasic.synchronizeds;

public class ShareData {
    
    int num;
    
    public synchronized void increase1() {
        num++;
    }
    
    public void increase2() {
        synchronized(this) {
            num++;
        }
    }
    
    public void increase3() {
        synchronized(ShareData.class) {
            num++;
        }
    }

    public int getNum() {
        return num;
    }
}

javap -c -l -s -v ShareData.class 命令查看字节码:

Classfile /E:/workspace170208/JavaBasicTest/target/classes/com/javabasic/synchronizeds/ShareData.class
  Last modified 2020-5-26; size 850 bytes
  MD5 checksum 666a7a0b1a6ab9b525f32276cb6cd699
  Compiled from "ShareData.java"
public class com.javabasic.synchronizeds.ShareData
  minor version: 0 //最小版本
  major version: 50 //最大版本
  flags: ACC_PUBLIC, ACC_SUPER //访问标志,ACC_PUBLIC是否为public类型, ACC_SUPER是否允许使用invokespecial字节码指令
Constant pool://常量池
   #1 = Class              #2             // com/javabasic/synchronizeds/ShareData
   #2 = Utf8               com/javabasic/synchronizeds/ShareData
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               num
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Methodref          #3.#11         // java/lang/Object."<init>":()V
  #11 = NameAndType        #7:#8          // "<init>":()V
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               Lcom/javabasic/synchronizeds/ShareData;
  #16 = Utf8               increase1
  #17 = Fieldref           #1.#18         // com/javabasic/synchronizeds/ShareData.num:I
  #18 = NameAndType        #5:#6          // num:I
  #19 = Utf8               increase2
  #20 = Utf8               StackMapTable
  #21 = Class              #22            // java/lang/Throwable
  #22 = Utf8               java/lang/Throwable
  #23 = Utf8               increase3
  #24 = Class              #25            // java/lang/Class
  #25 = Utf8               java/lang/Class
  #26 = Utf8               getNum
  #27 = Utf8               ()I
  #28 = Utf8               SourceFile
  #29 = Utf8               ShareData.java
{
  int num;
    descriptor: I
    flags:

  public com.javabasic.synchronizeds.ShareData();//默认构造方法
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #10                 // Method java/lang/Object."<init>":()V //调用超类构造方法,实例初始化方法,私有方法
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/javabasic/synchronizeds/ShareData;

  public synchronized void increase1();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED //同步方法标识
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0 //将第一个引用类型本地变量推送至栈顶
         1: dup ///复制栈顶数值并将复制值压入栈顶
         2: getfield      #17                 // Field num:I //获取指定类的实例域,并将其值压入栈顶
         5: iconst_1 //将int型1推送至栈顶
         6: iadd //将栈顶两个int型数值相加将结果压入栈顶
         7: putfield      #17                 // Field num:I //为指定的类的实例域赋值
        10: return //从当前方法返回void
      LineNumberTable:
        line 8: 0
        line 9: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lcom/javabasic/synchronizeds/ShareData;

  public void increase2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: aload_0 //将第一个引用类型本地变量推送至栈顶
         1: dup //复制栈顶数值并将复制值压入栈顶
         2: astore_1 //将栈顶引用型数值存入第二个本地变量
         3: monitorenter //获得对象的锁,用于同步方法或同步块
         4: aload_0 //将第二个引用类型本地变量推送至栈顶
         5: dup //复制栈顶数值并将复制值压入栈顶
         6: getfield      #17                 // Field num:I //获取指定类的实例域,并将其值压入栈顶
         9: iconst_1 //将int型1推送至栈顶
        10: iadd //将栈顶两个int型数值相加将结果压入栈顶
        11: putfield      #17                 // Field num:I //为指定的类的实例域赋值
        14: aload_1 //将第二个引用类型本地变量推送至栈顶
        15: monitorexit //释放对象的锁,用于同步方法或同步块
        16: goto          22 //无条件跳转
        19: aload_1 //将第二个引用类型本地变量推送至栈顶
        20: monitorexit //释放对象的锁,用于同步方法或同步块
        21: athrow //将栈顶的异常抛出
        22: return
      Exception table:
         from    to  target type
             4    16    19   any
            19    21    19   any
      LineNumberTable:
        line 12: 0
        line 13: 4
        line 12: 14
        line 15: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Lcom/javabasic/synchronizeds/ShareData;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 19
          locals = [ class com/javabasic/synchronizeds/ShareData, class com/javabasic/synchronizeds/ShareData ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 2

  public void increase3();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: ldc           #1                  // class com/javabasic/synchronizeds/ShareData
         2: dup
         3: astore_1
         4: monitorenter
         5: aload_0
         6: dup
         7: getfield      #17                 // Field num:I
        10: iconst_1
        11: iadd
        12: putfield      #17                 // Field num:I
        15: aload_1
        16: monitorexit
        17: goto          23
        20: aload_1
        21: monitorexit
        22: athrow
        23: return
      Exception table:
         from    to  target type
             5    17    20   any
            20    22    20   any
      LineNumberTable:
        line 18: 0
        line 19: 5
        line 18: 15
        line 21: 23
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      24     0  this   Lcom/javabasic/synchronizeds/ShareData;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 20
          locals = [ class com/javabasic/synchronizeds/ShareData, class java/lang/Class ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 2

  public int getNum();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #17                 // Field num:I
         4: ireturn
      LineNumberTable:
        line 24: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/javabasic/synchronizeds/ShareData;
}
SourceFile: "ShareData.java"

 

以上是关于synchronized底层原理的主要内容,如果未能解决你的问题,请参考以下文章

Synchronized的底层原理

想会用synchronized锁,先掌握底层核心原理

JVMday03类文件结构 字节码指令 多态的原理 异常 synchronized代码块底层原理

JVMday03类文件结构 字节码指令 多态的原理 异常 synchronized代码块底层原理

iOS synchronized底层原理分析

synchronize底层实现原理以及相关的优化