synchronized和ReentrantLock的区别

区别 synchronized ReentrantLock
底层实现 JVM内置的C++实现 Java代码,基于AQS框架实现
底层机制 Monitor 基于AQS框架实现
JVM实现 偏向锁、轻量级锁、重量级锁
可重入
可中断 lockInterruptibly()
非阻塞获取 tryLock()
公平性 非公平 可配置公平/非公平
锁释放 自动释放 手动释放
超时获取锁 不支持 tryLock(timeout)
条件变量 不支持 多个condition
锁状态检查 isLocked()

底层原理

synchronized的底层原理

字节码层面,synchronized会编译成monitorenter和monitorexit指令。
monitorenter指令会尝试获取锁,如果锁被其他线程持有,则当前线程会阻塞等待,直到锁被释放。
monitorexit指令会释放锁,允许其他线程获取锁。(monitorexit有两个,一个是正常退出,一个是异常退出)

每个对象都关联一个monitor,monitor记录了持有锁的线程、重入次数、等待队列等信息。

ReentrantLock的底层原理

Lock底层是基于AQS实现的,lock方法调用sync。sync的acquire方法,tryAcquire方法尝试获取锁,release方法释放锁。

  • state:同步状态(0表示未锁定,大于0表示锁定次数)
  • CLH队列:等待线程的双向队列
  • CAS:无锁的原子操作

使用方式

  • synchronized可以修饰方法、代码块,自动释放锁
  • 要先newReentrantLock(),并且ReentrantLock需要手动调用lock()和unlock()方法,需要在finally块中释放锁。(必须手动释放 不然会造成死锁)