接下来的几篇文章来记录下java里锁相关的知识点。

锁是用来控制多个线程访问共享资源的方式,在Lock之前,锁功能是靠synchronized实现的,Lock既然能出现,肯定是synchronized在有些情况下满足不了,我们来对比下两者的异同:

  1. 实现原理

    • synchronized,通过monitorenter/monitorexit两个指令来实现的,前者指令是在编译后插入到同步代码块开始位置,而后者指令是插入到方法结束和异常处,任何一个对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。
    • lock,主要通过同步器队列(AQS)及park/unpark实现。
  2. 出现异常时

    • synchronized,当出现异常时会自动释放锁,不会导致死锁。
    • lock,不会自动释放锁,需要在finally里显示释放。
  3. 是否可中断

    • synchronized,不能中断,必须等待线程执行完成。
    • lock,可以响应中断。
  4. 是否支持读写锁

    • synchronized,不支持读写锁。
    • lock,可通过ReadWriteLock实现读写锁。
  5. 是否可重入

    • synchronized,支持重入。
    • lock,可通过ReentrantLock实现可重入。
  6. 能否做到控制多个线程同时访问共享资源

    • synchronized,做不到。
    • lock,可以做到。
  7. 尝试非阻塞获取锁

    • synchronized,做不到,获取失败会一直阻塞在synchronized块外。
    • lock,可以做到,tryLock()方法,未获取到立即返回。
  8. 获取锁时指定超时时间

    • synchronized,做不到,获取失败会一直阻塞在synchronized块外。
    • lock,可以做到,tryLock(long time,TimeUnit unit)方法,超时后返回。

最后,再来看下Lock接口的方法:

image.png
其中的tryLock()尝试非阻塞的获取锁,调用该方法后立刻返回,获取到了锁返回true,否则返回false。
newCondition()获取等待通知组件,该组件和当前锁绑定,当前线程只有获取了锁才能调用此组件的wait()方法,调用后,当前线程将释放锁。
线程通过lockInterruptibly()获取锁失败会等待,如果其它线程调用了这个线程的interrupt(),那这个线程会从中断中返回,也就是响应中断。


步履不停
38 声望13 粉丝

好走的都是下坡路