用法:
a、指定加锁对象,对给定对象加锁;
synchronized(a){
...
}
b、直接作用于实例函数,对指定实例加锁;
public synchronized void f(){
...
}
c、直接作用于静态函数,对当前类加锁;
public static synchronized void f(){
...
}
原理:
1、synchronized作用于对象。反编译后会变成monitorenter和monitorexit这两个指令。
每个对象都有一个监视器锁(monitor),当monitor被占用就会处于锁定状态,线程执行monitorenter来尝试获取monitor的所有权。过程如下:
1、如果monitor进入数为0,该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者;
2、如果线程已经占有该monitor,只是重新进入,则进入数+1;
3、如果其他线程已经占用该monitor,则该线程阻塞,直到monitor进入数变为0,再重新尝试占用该monitor。
2、synchronized作用于方法。反编译后会发现方法的常量池会多了ACC_SYNCHRONIZED标识符,JVM就是根据该标识符来实现方法的同步的。方法执行时,先判断ACC_SYNCHRONIZED标识符是否被设置,被设置的话会先获取monitor,获取成功才会执行方法体,执行完毕在释放monitor。方法执行期间,任何其他线程都无法获取同一个monitor对象。
其他:
1、synchronized过程中,Thread.sleep并不会释放monitor锁,因而其他同步块依旧在等待。
2、synchronized过程中不响应中断。