Synchronized使用时一个不起眼的注意点
Synchronized 前情提要
Synchronized是Java中用来进行方法或者代码同步的一个内置锁机制。这种内置锁机制可以保证代码执行的原子性、可见性,但是并不能屏蔽代码的重排序。Synchronized可以修饰方法、对象以及代码块,并可以保证被修饰的方法或者代码块,在同一个时刻只能有一个线程能够访问得到。
- 修饰静态方法:锁的是当前类的class对象,修饰方法时Synchronized没有表现在字节码指令中,而是在class文件的方法表中将该方法的access_flags值置为1。表示该方法是同步方法,并使用调用该方法的对象或该方法所属的 Class 在 JVM 的内部对象表示 Klass 作为锁对象。
- 修饰普通方法:锁的是当前实例对象,修饰方法时同上。
- 修饰代码块:锁的是Synchronized()中的对象,编译后的字节码会在代码块前后插入monitorenter 和monitorexit。JVM需要每一个monitorenter都有一个monitorexit与之对应,任何对象都有一个monitor与之相对应,当一个monitor被持有,即线程执行到monitorenter时,对象将处于锁定状态。
Synchronized是Java内置的重量级锁,在jdk1.6之后引入了自旋锁、轻量级锁、适应性自旋、锁粗化、锁消除、偏向锁等技术来减少Synchronized的性能开销。