synchronized 底层实现原理?

synchronized 底层实现原理?

一、作用

  • 确保线程互斥的访问同步代码
  • 保证共享变量的修改能够及时可见
  • 有效解决重排序问题

 

二、用法

  • 修饰普通方法
  • 修饰静态方法
  • 修饰代码块

 

三、原理

  • 同步代码块是通过 monitorenter 和 monitorexit 指令获取线程的执行权
  • 同步方法通过加 ACC_SYNCHRONIZED 标识实现线程的执行权的控制

测试代码:

public class TestSynchronized {
	
	public void sync() {
		synchronized (this) {
			System.out.println("sync");
		}
	}
	
	public synchronized void syncdo() {
		System.out.println("syncdo");
	}
	
	public static synchronized void staticSyncdo() {
		System.out.println("staticSyncdo");
	}
}

通过JDK 反汇编指令 javap -c -v TestSynchronized

javap -c -v TestSynchronized

  Last modified 2019-5-27; size 719 bytes
  MD5 checksum e5058a43e76fe1cff6748d4eb1565658
  Compiled from "TestSynchronized.java"
public class constxiong.interview.TestSynchronized
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // constxiong/interview/TestSynchronized
   #2 = Utf8               constxiong/interview/TestSynchronized
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lconstxiong/interview/TestSynchronized;
  #14 = Utf8               sync
  #15 = Fieldref           #16.#18        // java/lang/System.out:Ljava/io/PrintStream;
  #16 = Class              #17            // java/lang/System
  #17 = Utf8               java/lang/System
  #18 = NameAndType        #19:#20        // out:Ljava/io/PrintStream;
  #19 = Utf8               out
  #20 = Utf8               Ljava/io/PrintStream;
  #21 = String             #14            // sync
  #22 = Methodref          #23.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #23 = Class              #24            // java/io/PrintStream
  #24 = Utf8               java/io/PrintStream
  #25 = NameAndType        #26:#27        // println:(Ljava/lang/String;)V
  #26 = Utf8               println
  #27 = Utf8               (Ljava/lang/String;)V
  #28 = Utf8               syncdo
  #29 = String             #28            // syncdo
  #30 = Utf8               staticSyncdo
  #31 = String             #30            // staticSyncdo
  #32 = Utf8               SourceFile
  #33 = Utf8               TestSynchronized.java
{
  public constxiong.interview.TestSynchronized();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lconstxiong/interview/TestSynchronized;

  public void sync();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         3: monitorenter
         4: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         7: ldc           #21                 // String sync
         9: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        12: aload_1
        13: monitorexit
        14: goto          20
        17: aload_1
        18: monitorexit
        19: athrow
        20: return
      Exception table:
         from    to  target type
             4    14    17   any
            17    19    17   any
      LineNumberTable:
        line 6: 0
        line 7: 4
        line 6: 12
        line 9: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  this   Lconstxiong/interview/TestSynchronized;

  public synchronized void syncdo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #29                 // String syncdo
         5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 12: 0
        line 13: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lconstxiong/interview/TestSynchronized;

  public static synchronized void staticSyncdo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #31                 // String staticSyncdo
         5: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 16: 0
        line 17: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}
SourceFile: "TestSynchronized.java"

深入分析可参考:

https://www.cnblogs.com/paddix/p/5367116.html 

javap指令

 


【Java面试题与答案】整理推荐

 

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值