前言

synchronized是Java中解决并发问题的一种常用方法,它主要的作用如下

  • 确保线程互斥的访问代码
  • 保证变量的可见性
  • 解决重排序

 

基本使用

synchronized可以修饰方法、代码块,下面看一个简单的例子

public class SynTest {
    
    public void lockTest() {
        synchronized (this) {
            System.out.println(233);
        }
    }
}

对这段代码使用javap -c SysTest.class进行反编译

Compiled from "SynTest.java"

public class com.happycode.lock.SynTest {
  public com.happycode.lock.SynTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
 
  public void lockTest();
    Code:
       0: aload_0
       1: dup
       2: astore_1
       3: monitorenter
       4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: sipush        233
      10: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      13: aload_1
      14: monitorexit
      15: goto          23
      18: astore_2
      19: aload_1
      20: monitorexit
      21: aload_2
      22: athrow
      23: return
    Exception table:
       from    to  target type
           4    15    18   any
          18    21    18   any
}

我们需要关注的是monitorenter和monitorexit指令,这些是jvm提供的,每个对象有一个监视器锁(Monitor),当 Monitor 被占用时就会处于锁定状态。monitorenter指令回去尝试获取Monitor,如果Monitor的计数器为0,则获取成功,线程进入,Monitor计数器加1,如果不为0,线程就会阻塞。也能看出synchronized是非公平的。其实wait和notify也依赖监视器Monitor。这就是为什么他们只能在synchronized块里。

 

 

                                                               

synchronized深入探究_System