1、底层结构不同
synchronized 是关键字,由JVM底层实现。(底层是通过monitor对象来完成:monitorenter/monitorexit)
lock 是具体的接口(java.util.concurrent.locks.lock),是API层面的锁。
2、使用方法
synchronized 不需要手动释放锁,代码执行完后,系统会自动释放线程占有的锁。
ReentrantLock 需要手动释放锁,若没有主动释放,可能会导致死锁。
需要lock()、unlock() 配合try/finally语句块来使用。
3、等待是否可中断
synchronized 不可中断,除非抛出异常或代码正常运行完成。
ReentrantLock 可中断。
(1)设置超时方法tryLock(long timeout, TimeUnit unit)
(2) lockInterruptibly() 放代码块中,调用 interrupt()方法可中断。
4、加锁是否公平
synchronized 是非公平锁。
ReentrantLock 两者都可。默认是非公平锁。不过可通过构造方法传入true创建公平锁;false非公平锁。
5、锁是否可以绑定多个条件Condition
synchronized 没有。
ReentrantLock 可以分组唤醒需要唤醒的线程,可以精确唤醒。而不是像synchronized要么随机唤醒一个线程,要么唤醒全部线程。
引申:
普通版:加锁--等待--唤醒
synchronized、wait()、notify()。
升级版:加锁--等待--唤醒
ReentrantLock、await()(先lock.newCondition()得到Condition)、signal()。