java synchronized原理

2020-12-01

一 sysnchronized的作用

  • 保证代码互斥的访问临界区(每次只允许一个线程访问的区域)
  • 保证共享资源的修改能够及时可见

二 用法

  1. 修饰代码块
  2. 修饰普通方法
  3. 修饰静态方法

三 个人理解

同步块就相当于在方法内限定了一个小范围的--局部临界区,synchronized的对象就相当于学操作系统进程同步信号量机制的那个信号量,只不过这个信号量为1,因为jvm限定了只能有一个线程拿到(修改)这个"信号量"。

而同步方法、同步静态方法就相当于整个方法作用域都作为临界区。

javap反编译可以看到进入同步块前后由两个指令,monitorenter和monitorexit.


Compiled from "Human.java"
public class com.backgulf.tyrell.Human {
  public com.backgulf.tyrell.Human();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iconst_0
       6: putfield      #2                  // Field age:I
       9: return

  public void method1();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: sipush        1000
       6: if_icmpge     67
       9: aload_0
      10: dup
      11: astore_2
      12: monitorenter
      13: aload_0
      14: dup
      15: getfield      #2                  // Field age:I
      18: iconst_1
      19: iadd
      20: putfield      #2                  // Field age:I
      23: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: new           #4                  // class java/lang/StringBuilder
      29: dup
      30: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      33: ldc           #6                  // String 生产一张还有:
      35: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: aload_0
      39: getfield      #2                  // Field age:I
      42: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      45: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      48: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      51: aload_2
      52: monitorexit
      53: goto          61
      56: astore_3
      57: aload_2
      58: monitorexit
      59: aload_3
      60: athrow
      61: iinc          1, 1
      64: goto          2
      67: return
    Exception table:
       from    to  target type
          13    53    56   any
          56    59    56   any

但是对于同步方法来说常量池中多了ACC_SYNCHRONIZED标示符,所以使用synchronized时应注意这个"信号量"锁是不是加在同一个上。

## 今天也是想你的一天 ^_^~