并发的高级知识:lock、condition、ReadWriteLock接口

1,700 阅读3分钟

LOck介绍

lock对象主要是是对sychronize关键字的扩展主要特点:

  1. sychronize获取监控锁会直接进入block状态,或者等待时间耗尽返回。lock可以trylock返回结果,非阻塞任务中需要
  2. 进程在获取多个锁的时候,获取顺序与释放顺序相反。lock对象不要求,应用更为灵活。
  3. lock可以多次获取,例如ReadWriteLock.

lock接口函数介绍

  1. void lock()获取锁,如果lock无效的话,进入等待状态,不能被中断
  2. void lockInterruptibly() throws InterruptedException 中断锁。进入等待状态后可以被中断
  3. boolean tryLock()尝试获取锁。无效直接返回
  4. boolean tryLock(long time,TimeUnit unit) throws InterruptedException尝试获取锁,如果无效等待一定时间。
  5. void unlock()释放锁
  6. Condition newCondition()返回锁关联的状态对象。

condition接口

condition借口就是实现object对象的wait(),notify(),notifyAll()。主要区别是是子类可以实现相应功能,并加以丰富。相关函数

  1. void await() throws InterruptedException调用等待,进入condition的等待集。
  2. void awaitUninterruptibly()调用等待,进入condition的等待集,不可以被中断。
  3. long awaitNanos(long nanosTimeout) throws InterruptedException 调用等待,进入condition的等待集,当时间过去的时候也会触发中断。
  4. boolean await(long time,TimeUnit unit) throws InterruptedException 功能同上
  5. boolean awaitUntil(Date deadline) throws InterruptedException功能与上类似
  6. void signal()选中等待condition的继承,进入等待lock状态
  7. void signalAll()同时所有的等待状态。 注意condition同wait一样,在实施相关函数之前,要获取锁。condition获取的是lock对象,wait获取的是对象自身的监控锁

用法示例:

 boolean aMethod(long timeout, TimeUnit unit) {
   long nanos = unit.toNanos(timeout);
   lock.lock();
   try {
     while (!conditionBeingWaitedFor()) {
       if (nanos <= 0L)
         return false;
       nanos = theCondition.awaitNanos(nanos);
     }
     // ...
   } finally {
     lock.unlock();
   }
 }

ReadWriteLock接口

是在在互斥锁的基础上进行功能扩展的锁,允许多个进程进行读,当在写进程很少的时候,可以大大提高效率。设计问题,读写进程的优先级以及读写策略问题。

  1. Lock readLock()
  2. Lock writeLock()

ReentrantLock lock子类

实现lock接口,可以对block进程实现fair算法,等待时间长的进程有限获得拥有锁。fair算法的会导致程序性能下降,并且对进程饥饿与等待时间影响较小。建议采用默认的非fair lock。


用法

   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }

相关函数:

  1. public ReentrantLock()默认非fairlock
  2. public ReentrantLock(boolean fair)根据需求选择什么样的lock
  3. public void lock()获取锁,如果不能获取锁的话,进入等待
  4. public void lockInterruptibly()throws InterruptedException 获取锁,如果不能获取锁的话,进入等待,可以被中断
  5. public boolean tryLock()尝试获取锁,true获取锁,false 没有获取锁
  6. public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException 在给定的时间获取锁。
  7. public void unlock()释放锁
  8. public Condition newCondition()创建一个condition对象。当用conditon wait的时候lock的锁自动释放,以FIFO的形式在等待condition中被激活,激活后需要重新获取lock
  9. public int getHoldCount()返回进程获取lock的次数,用于unlock函数。也可以在lock之前获取该值,不用重新lock
  10. public boolean isHeldByCurrentThread()是否被当前进程拥有
  11. public boolean isLocked()是否locked
  12. public final boolean isFair()是否fair
  13. protected Thread getOwner()返货lock的拥有者
  14. public final boolean hasQueuedThreads()protected Collection getQueuedThreads();public final int getQueueLength()是否被等待,等待的线程集合,等待线程数量。注意数值不一定准确。
  15. public boolean hasWaiters(Condition condition);public int getWaitQueueLength(Condition condition);protected Collection getWaitingThreads(Condition condition)同上只是针对condition的
  16. public String toString()

ReentrantReadWriteLock类

实现了readerwriterlock接口,

  1. 获得顺序:a、无序,默认,效率高。b,fair,优先调用等待时间长的进程,性能低。
  2. 是否可以重新获取锁:write锁可以获得读锁,反之 不行
  3. 锁性能降低:写的锁可以变为读锁,反之不行。意思同上
  4. 读写lock可以被中断
  5. condition支持,写的。读lock无condition
  6. 指令,有些指令只是合适监控的。不是进程通信的,阻塞信息。 相关函数与entrantlock相同,不解释

引用

tutorial

官方库介绍