https://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html
Synchronized实现原理
Java中的每一个对象都可以作为锁,而在Synchronized实现同步的几种方式中分别为:
- 普通同步方法:锁是当前实例对象
- 静态同步方法:锁是当前类的Class对象
- 同步方法块:锁是Synchronized括号里配置的对象
任何一个对象都一个Monitor与之关联,当且一个Monitor被持有后,它将处于锁定状态。Synchronized在JVM里的实现都是基于进入和退出Monitor对象来实现方法同步和代码块同步,虽然具体实现细节不一样,但是都可以通过成对的MonitorEnter和MonitorExit指令来实现。MonitorEnter指令插入在同步代码块的开始位置,当代码执行到该指令时,将会尝试获取该对象Monitor的所有权,即尝试获得该对象的锁,而monitorExit指令则插入在方法结束处和异常处,JVM保证每个MonitorEnter必须有对应的MonitorExit。
链接:http://www.infoq.com/cn/articles/java-se-16-synchronized/
Synchronized和ReenternLock区别
ReenternLock使用的CAS策略,不会频繁的挂起和恢复线程,而Synchronized是重量级锁,性能上不如ReenternLock,但在JDK 1.6 有了锁优化以后使用这两个在性能上相差无几。偏向锁,轻量级锁,重量级锁
此外RennternLock的使用方法更加的丰富,可以尝试获取锁,可以设置等待时间,可以响应中断,可以设置公平锁还是不公平锁等。
但是相比Synchronized的使用有个缺点的地方是需要手动的释放锁,使用起来不如Sychronized方便
所以在使用的时候还是看情况。
CAS中可能会出现的问题
在CAS操作中,会出现ABA问题。就是如果V的值先由A变成B,再由B变成A,那么仍然认为是发生了变化,并需要重新执行算法中的步骤。有简单的解决方案:不是更新某个引用的值,而是更新两个值,包括一个引用和一个版本号,即使这个值由A变为B,然后为变为A,版本号也是不同的。AtomicStampedReference和AtomicMarkableReference支持在两个变量上执行原子的条件更新。AtomicStampedReference更新一个“对象-引用”二元组,通过在引用上加上“版本号”,从而避免ABA问题,AtomicMarkableReference将更新一个“对象引用-布尔值”的二元组。