接下来的几篇文章来记录下java里锁相关的知识点。
锁是用来控制多个线程访问共享资源的方式,在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接口的方法:
其中的tryLock()尝试非阻塞的获取锁,调用该方法后立刻返回,获取到了锁返回true,否则返回false。
newCondition()获取等待通知组件,该组件和当前锁绑定,当前线程只有获取了锁才能调用此组件的wait()方法,调用后,当前线程将释放锁。
线程通过lockInterruptibly()获取锁失败会等待,如果其它线程调用了这个线程的interrupt(),那这个线程会从中断中返回,也就是响应中断。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。