synchronized和ReentrantLock底层原理差别

网上很多synchronized和ReentrantLock使用和编程时写法差异的总结,这里就不列举了;

这里主要列举一下在底层实现上的一些区别:

1、synchronized

      synchronized关键字需要一个引用类型的参数,这个参数也叫做监听器(monitor);JVM通过这个监听器来管理所有需要同步的线程(synchronized这个监听器的所有线程)运行状态,成功占有该monitor的线程即成为该监听器的owner,其他线程则被状态切换至阻塞状态并维护在一个队列中准备下一次的竞争;

线程状态可用下图表明:

------------------------------------------------   pic -------------------------------------------------------------------

synchronized和ReentrantLock底层原理差别

------------------------------------------------   pic -------------------------------------------------------------------

 

大家知道线程在不同状态之间切换是比较消耗cpu资源的,所以使用synchronized处理较大并发的场景性能开销是比较大的;

(大致可以这样理解,如果有兴趣可以查看反编译带有synchronized的class文件,内在实现还是挺复杂的)

 

2、ReentrantLock

以非公平锁为例

多个线程调用同一个ReentrantLock对象的lock()方法时,大致原理是每个线程都尝试去修改锁对象内一个状态属性state(继承自java.util.concurrent.locks.AbstractQueuedSynchronizer)的值,这个修改过程采用了CAS(compare  and swap)技术即每个线程都想把这个变量从数值0改变成1;

如果一个线程修改成功则成功锁对象的owner,否则LockSupport.park中止该线程,并调用改线程的interrupt方法设置线程的interrupted状态,并创建一个node存放该线程并将node加入链表中;

当某线程a调用unlock方法时,从链表中取出a线程对应node的next节点并调用LockSupport.unpark给对应线程一个许可让其继续执行;