synchronized关键字

线程安全的主要来源就是JMM的设计,主要集中在主内存和线程工作内存而导致的内存可见性问题以及重排序导致的问题。java的synchronized关键字具有使每个线程依次排队操作共享变量的功能。但是,这种同步机制效率很低,但是synchronized是其他并发容器实现的基础。

1.synchronized实现原理

synchronized可以使用在代码块和方法中,具体使用位置如下:



synchronized可以用在方法上也可以用在代码块中,其中方法是静态方法和实例方法锁住的分别是类对象和实例对象。如果锁住的是类对象的话,尽管new多个实例对象,但他们仍然属于一个类,依然会被锁住,即线程之间保证同步关系。

1.1对象锁机制

public class SynchronizedDemo {
    public static void main(String[] args) {
        synchronized (SynchronizedDemo.class) {
        }
        method();
    }

    private static void method() {
    }
}

上述代码有一个同步代码块,锁住的是类对象。切换到SynchronizedDemo.class的同级目录之后,然后用javap -v SynchronizedDemo.class查看字节码文件:


黄色部分就是添加synchronized关键字后独有的。执行同步代码块首先要知名monitorenter指令,退出执行monitorexit执行。使用Synchronized进行同步,关键是要对对象监视器monitor进行获取,当线程获取monitor后才能继续执行,否则只能等待。而这个获取的过程是互斥的,同一时刻只有一个线程能够获取到monitor。上面的demo中在执行完同步代码块之后紧接着再会去执行一个静态同步方法,而这个方法锁的对象依然就这个类对象,那么这个正在执行的线程还需要获取该锁吗?答案是不必的,从上图中就可以看出来,执行静态同步方法的时候就只有一条monitorexit指令,并没有monitorenter获取锁的指令。这就是锁的重入性,即在同一锁程中,线程不需要再次获取同一把锁。Synchronized先天具有重入性。每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会加一,释放锁后就会将计数器减一。

1.2synchronized的happens-before关系

Synchronized的happens-before规则,即监视器锁规则:对同一个监视器的解锁,happens-before于对这个监视器的加锁。

你可能感兴趣的:(synchronized关键字)