一、概述1、synchronized作用

    原子性:synchronized保证语句块内操作是原子的
    可见性:synchronized保证可见性(通过“在执行unlock之前,必须先把此变量同步回主内存”实现)
    有序性:synchronized保证有序性(通过“一个变量在同一时刻只允许一条线程对其进行lock操作”)
    2、synchronized的使用

    修饰实例方法,对当前实例对象加锁
    修饰静态方法,多当前类的Class对象加锁
    修饰代码块,对synchronized括号内的对象加锁
    二、实现原理

    1、jvm基于进入和退出Monitor对象来实现方法同步和代码块同步。

    方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。JVM可以从方法常量池中的方法表结构(method_info Structure) 中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。当方法调用时,调用指令将会 检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor(虚拟机规范中用的是管程一词), 然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放monitor。

    代码块的同步是利用monitorenter和monitorexit这两个字节码指令。它们分别位于同步代码块的开始和结束位置。当jvm执行到monitorenter指令时,当前线程试图获取monitor对象的所有权,如果未加锁或者已经被当前线程所持有,就把锁的计数器+1;当执行monitorexit指令时,锁计数器-1;当锁计数器为0时,该锁就被释放了。如果获取monitor对象失败,该线程则会进入阻塞状态,直到其他线程释放锁。

    这里要注意:

    synchronized是可重入的,所以不会自己把,自己锁死
    synchronized锁一旦被一个线程持有,其他试图获取该锁的线程将被阻塞。
    关于ACC_SYNCHRONIZED 、monitorenter、monitorexit指令,可以看一下下面的反编译代码: