深入分析 JUC 之 Lock 接口
锁是用来控制多个线程访问共享资源的方式,在 Lock 之前,锁功能是靠 synchronized 实现的,Lock 既然能出现,肯定是 synchronized 在有些情况下满足不了,我们来对比下两者的异同:
一、实现原理
synchronized,通过 monitorenter/monitorexit 两个指令来实现的,前者指令是在编译后插入到同步代码块开始位置,而后者指令是插入到方法结束和异常处,任何一个对象都有一个 monitor 与之关联,当且一个 monitor 被持有后,它将处于锁定状态。
lock,主要通过同步器队列(AQS)及 park/unpark 实现。
二、出现异常时
synchronized,当出现异常时会自动释放锁,不会导致死锁。
lock,不会自动释放锁,需要在 finally 里显示释放。
三、是否可中断
synchronized,不能中断,必须等待线程执行完成。
lock,可以响应中断。
四、是否支持读写锁
synchronized,不支持读写锁。
lock,可通过 ReadWriteLock 实现读写锁。
五、是否可重入
synchronized,支持重入。
lock,可通过 ReentrantLock 实现可重入。
六、能否做到控制多个线程同时访问共享资源
synchronized,做不到。
lock,可以做到。
七、尝试非阻塞获取锁
synchronized,做不到,获取失败会一直阻塞在 synchronized 块外。
lock,可以做到,tryLock()方法,未获取到立即返回。
八、获取锁时指定超时时间
synchronized,做不到,获取失败会一直阻塞在 synchronized 块外。
lock,可以做到,tryLock(long time,TimeUnit unit)方法,超时后返回。
最后,再来看下 Lock 接口的方法:
![](https://static001.geekbang.org/infoq/58/58d18e71eac452d417acd9e2fb1ba190.png)
其中的 tryLock()尝试非阻塞的获取锁,调用该方法后立刻返回,获取到了锁返回 true,否则返回 false。newCondition()获取等待通知组件,该组件和当前锁绑定,当前线程只有获取了锁才能调用此组件的 wait()方法,调用后,当前线程将释放锁。java培训
评论