synchronized的原理及其使用说明

先看段代码

public class Test2 {

    public synchronized void test() {
        System.out.println("hello");
    }

    public void test3() {
        synchronized (this) {
            System.out.println("hello");
        }
    }

    public static synchronized void test2() {
        System.out.println("hello");
    }

}

常用用法,修饰对象,方法,静态方法

看原理

使用javap -c xx.class > 1.txt

 public synchronized void test();
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String hello
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

  public void test3();
    Code:
       0: aload_0
       1: dup
       2: astore_1
       3: monitorenter
       4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       7: ldc           #3                  // String hello
       9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      12: aload_1
      13: monitorexit
      14: goto          22
      17: astore_2
      18: aload_1
      19: monitorexit
      20: aload_2
      21: athrow
      22: return
    Exception table:
       from    to  target type
           4    14    17   any
          17    20    17   any

  public static synchronized void test2();
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String hello
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

对应上面的代码,class字节码

可以看出本质monitorenter和monitorexit指令

同步方法其实是

flags: ACC_SYNCHRONIZED,需要反编译成汇编可以直观地看见底层实现。

实际上,锁的本质满足如下:

1、原子性:当一个线程操作共享变量的时候,其他线程不能操作。实际就是串行修改。

2、可见性:当一个线程修改一个变量的时候,其他的线程及时知道更新缓存变量(参考计算机原理CPU与内存或主存的交互设计)

3、(可选)可重入:当一个线程拿到某个锁后,当该线程在释放该锁之前,可以重复获取该锁,当然释放次数与获取次数相同,否则死锁

从上可看出synchronized 的用途

1. 对于同步方法,锁是当前实例对象。

2. 对于同步方法块,锁是Synchonized括号里的对象。

3. 对于静态同步方法,锁是当前对象的Class对象。类似 synchronized (this.class)

JDK8及以后的版本JDK对synchronized做了优化,对于写操作频繁的线程安全推荐使用,性能较强

synchronized是操作对象头的monitor实现的,所以当时用sleep和wait的时候,在sleep方法中没有释放monitor,所以锁未释放,而wait方法释放了monitor对象,释放了锁

猜你喜欢

转载自blog.csdn.net/fenglllle/article/details/81296250
今日推荐