Synchronized关键字解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chao821/article/details/84035836

一、Synchronized用法

synchronized是Java提供的一个并发控制的关键字。主要有两种用法,分别是同步方法和同步代码块。也就是说,synchronized既可以修饰方法也可以修饰代码块。代码如下:

/**
 * @author Hollis 18/08/04.
 */
public class SynchronizedDemo {
     //同步方法
    public synchronized void doSth(){
        System.out.println("Hello World");
    }

    //同步代码块
    public void doSth1(){
        synchronized (SynchronizedDemo.class){
            System.out.println("Hello World");
        }
    }
}

synchronized修饰的代码块及方法,在同一时间,只能被单个线程访问。

二、Synchronized同步原理

synchronized,是Java中用于解决并发情况下数据同步访问的一个很重要的关键字。当我们想要保证一个共享资源在同一时间只会被一个线程访问到时,我们可以在代码中使用synchronized关键字对类或者对象加锁。下面简单介绍其原理,我们对上面的代码进行反编译,可以得到如下代码:

public synchronized void doSth();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello World
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return

  public void doSth1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #5                  // class com/hollis/SynchronizedTest
         2: dup
         3: astore_1
         4: monitorenter
         5: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: ldc           #3                  // String Hello World
        10: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        13: aload_1
        14: monitorexit
        15: goto          23
        18: astore_2
        19: aload_1
        20: monitorexit
        21: aload_2
        22: athrow
        23: return

通过反编译后代码可以看出:

对于同步方法,JVM采用ACC_SYNCHRONIZED标记符来实现同步。 

对于同步代码块。JVM采用monitorentermonitorexit两个指令来实现同步。

无论是ACC_SYNCHRONIZED还是monitorentermonitorexit都是基于Monitor实现的,在Java虚拟机(HotSpot)中,Monitor是基于C++实现的,由ObjectMonitor实现。

三、Sychronized特性

1)原子性

在Java中,为了保证原子性,提供了两个高级的字节码指令monitorentermonitorexit。前面介绍过,这两个字节码指令,在Java中对应的关键字就是synchronized。通过monitorentermonitorexit指令,可以保证被synchronized修饰的代码在同一时间只能被一个线程访问,在锁未释放之前,无法被其他线程访问到

2)可见性

可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。所以,就可能出现线程1改了某个变量的值,但是线程2不可见的情况。前面我们介绍过,被synchronized修饰的代码,在开始执行时会加锁,执行完成后会进行解锁。而为了保证可见性,有一条规则是这样的:对一个变量解锁之前,必须先把此变量同步回主存中。这样解锁后,后续线程就可以访问到被修改后的值。所以,synchronized关键字锁住的对象,其值是具有可见性的。

扫描二维码关注公众号,回复: 4390988 查看本文章

猜你喜欢

转载自blog.csdn.net/chao821/article/details/84035836