synchronized关键字
- JDK 1.5之前的synchronized关键字,锁被称之为重量级锁
- synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的。
- 其底层依赖监视器
- 监视器又依赖操作系统底层的互斥锁
- 1.6之后为了减少获得锁和释放锁带来的性能开销而引入偏向锁和轻量级锁,优化之后原来越强大了,这也是官方建议使用synchronized的原因
java的线程是内核映射的,如果获取不到锁,那么就必然会发生内核态与用户态的转换,成本很高,所以效率比较低.
Synchonized实现同步的基础
Java中每一个对象都可以作为锁。具体有如下三种形式:
-
对于普通同步方法,锁是当前实例对象。
-
对于静态同步方法,锁是当前类的Class对象。
-
对于同步代码块,锁是synchronized括号里配置的对象。
public class SynchronizedTest {
/**
* 同步修饰普通方法
*/
public synchronized void test01() {
// 同步修饰代码块
synchronized (this) {
System.out.println("hello synchronized");
}
}
/**
* 同步修饰静态方法
*/
public synchronized static void test02() {
}
}
使用javap 查看生成的class 文件
javap -verbose ***.class
从JVM规范中可以看到Synchronized在JVM里的实现原理,JVM基于进入和退出monitor对象来实现方法同步和代码块同步的,但两者的实现细节不一样。
代码块同步:
是使用monitorenter指令在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法的结束处和异常处,然后执行完对应操作后,在monitorexit监视器出口释放锁。
方同步法:
而方法同步是使用另外一种方式实现的,细节在JVM规范里并没有详细说明。但是,方法的同步同样可以使用这两个指令来实现。在class文件中synchronized被ACC_SYNCHRONIZED标记,表明该方法为同步方法。
静态同步方法:
使用