synchronized修饰
1.使用在静态方法上
public synchronized static void incr(){
...
}
2.使用在方法中( ①对所有方法体加锁, ②对某个代码块加锁)
public void demo(){
synchronized(this){
...
}
}
synchronized作用域
1.全局锁
//1.全局锁(加到 static 静态方法上的)
public synchronized static void incr(){
...
}
//2.全局锁(加到方法中,锁住的是当前类.class的)
public void demo(){
synchronized(类.class){
...
}
}
2.当前对象锁
//1.当前对象锁(锁在方法上,锁住的是 this )
public void demo(){
synchronized(this){
...
}
}
//实例↓↓↓
public static void main(String[] args){
Demo demo01 = new Demo();
demo01.demo();
Demo demo02 = new Demo();
demo02.demo();
//demo01 和 demo02 之间的锁是互不影响的
}
public static void main(String[] args){
Demo demo01 = new Demo();
demo01.demo();
demo01.demo();
//这种情况下,同一实例多处调用,则会存在锁的等待
}
3.任何一个对象,都可以成为一把锁
1.当前对象锁(lock不是一个静态的成员对象,那么这个时候,这种锁是实例级别)
public class Demo{
//定义了一把锁(当前对象锁)
Object lock = new Object();
public void demo(){
synchronized(lock){
...
}
}
public static void main(String[] args){
//main方法
}
}
2.全局锁(static修饰的 lock 锁,就是全局锁了)
public class Demo{
//定义了一把锁(全局锁)
static Object lock = new Object();
public void demo(){
synchronized(lock){
...
}
}
public static void main(String[] args){
//main方法
}
}
简单原理
1.synchronized 在 静态方法上
public synchronized static void incr(){
...
}
字节码中, flags属性中,会增加一个:ACC_SYNCHRONIZED属性(如下图,图片来自网络,仅做部分了解)
2.synchronized 在方法里面
public void demo(){
synchronized(this){
...
}
}
字节码中,会增加两个指令:monitorenter
monitorexit
为什么会是有两个 monitorexit 呢?
是这样的,编译器需要确保方法中调用过的每条 monitorenter 指令都要执行对应的 monitorexit 指令。为了保证在方法异常时,monitorenter 和 monitorexit 指令也能正常配对执行,编译器会自动产生一个异常处理器,它的目的就是用来执行异常的monitorexit 指令。而字节码中多出的 monitorexit 指令,就是异常结束时,被执行用来释放 monitor 的。
错误观点问题
1.我听说 synchronized 是重量级锁,性能特别低是这样么?
这句话不全对,JDK1.5以后对 synchronized 进行了大刀阔斧的优化,这其中涉及到自旋锁、偏向锁、轻量级锁、重量级锁、锁膨胀、锁消除等手段。
synchronized 锁的用法,介绍到此为止
如果本文对你有所帮助,那就给我点个赞呗 ^_^
End