一、概述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指令,可以看一下下面的反编译代码: