赞
踩
大家好,我是wave,这次来和大家详细的聊一聊Synchronized这个关键字,希望大家看完可以对synchronized关键字有一个非常全面的了解。
synchronized主要有三种使用方式:
修饰实例方法: 给一个类上的方法添加synchronized关键字,这个锁会作用于这个类当前的实例对象上,进入同步代码前要获得 当前对象实例的锁
public synchronized void method(){
// do something
}
修饰静态方法: 由于静态方法属于类,就相当于给一个类加了锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁
public synchronized static void method(){
// do something
}
修饰代码块 :指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁。synchronized(类.class) 表示进入同步代码前要获得 当前 class 的锁
public class Solution { public void method(){ synchronized (this){ //给当前对象加锁 } synchronized (Solution.class){ //给Solution这个类加锁 } Object lock = new Object(); synchronized (lock){ //给Object这个对象加锁 } } }
synchronized在JDK早期是一个非常重量级的锁,依靠JVM的指令对代码块进行加锁,所以synchronized是JVM层面的锁,而Lock是用Java代码实现的,所以可以看作是API层面的锁。但是后续JDK对synchronized进行了非常多的优化和升级,目前synchronized与Lock的效率已经相差不多了。
synchronized修饰代码块是用两个指令monitorenter、monitorexit完成的,口说无凭,我带大家看一看字节码吧~
public class Solution {
public void method(){
synchronized (this){
System.out.println("synchronized修饰代码块");
}
}
}
- 首先写一段这样的代码,然后可以通过javap来查看它的字节码。如果使用IDEA的话可以经过一点小小的配置就可以在控制台直接输出字节码了,先给大家看看IDEA应该如何配置
- File->setting->Tools->External->左上角的+号,里面中间的三个配置分别为:
$
JDKPath$
\bin\javap.exe- -verbose -p -c
$
FileClass$
$
OutputPath$
- 然后编译一下程序,按运行旁边的绿色小锤子就可以了,再右键打开External tool找到刚才配置的工具,就可以在控制台打印出字节码了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i0NuCB6I-1608209600129)( http://gtwave.gitee.io/image/images/wechart/synchronized字节码.png)]
现在我说synchronized加在同步代码块上是用JVM指令来实现的就没啥问题了吧~当JVM执行到monitorenter的时候线程试图获取锁也就是获取 对象监视器 monitor 的持有权。
public class Solution {
public synchronized void method(){
System.out.println("synchronized 修饰方法");
}
}
可以看到修饰一个方法就会有一个ACC_SYNCHRONIZED标识,代表这个方法是同步方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。