重入锁的好搭档:Condition条件
在线程交互中,我们介绍了线程之间的交互,主要通过两个函数完成,Object.wait()
和Object.notify()
,这两个函数搭配synchronized
关键字使用。而Condition
有着大致相同的功能,它与重入锁相关联,因此Condition
一般都是作为Lock
的内部实现。。通过Lock
接口的Condition newCondition()方法
生成一个和重入锁关联的Condition
实例。利用Condition
对象,可以让线程在合适的时间等待,或在某一时刻得到通知继续执行。
![](https://img.haomeiwen.com/i17253929/4e0cabd48347b9b0.png)
Condition
接口提供的基本方法:
public interface Condition {
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long var1) throws InterruptedException;
boolean await(long var1, TimeUnit var3) throws InterruptedException;
boolean awaitUntil(Date var1) throws InterruptedException;
void signal();
void signalAll();
}
-
await()
方法会使线程等待,同时释放当前锁,当前线程加入Condition
对象维护的等待队列中,当其他线程中使用signal()
或signalAll()
方法时,线程会重新获得锁继续执行。或当线程被中断时,也会跳出等待。 -
awaitUninterruptibly()
方法与await()
方法基本相同,但它不会在等待过程中响应中断。 -
signal()
方法用于唤醒一个在等待中的线程。signalAll()
方法会唤醒所有在等待的线程。
Condition
示例
package reenterLock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Time : 2019/05/06 上午 09:58
* @Author : xiuc_shi
**/
public class ReenterLockCondition implements Runnable {
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
@Override
public void run() {
lock.lock();
try {
condition.await();
System.out.println("线程继续执行");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLockCondition tl = new ReenterLockCondition();
Thread t1 = new Thread(tl);
t1.start();
Thread.sleep(2000);
lock.lock();
condition.signal();
lock.unlock();
}
}
子线程获得锁后,通过一个与重入锁lock
相关联的Condition
对象执行await()
方法,从而释放锁;主线程获得该重入锁,然后执行signal()
方法通知子线程可以继续执行,最后释放锁以让子线程获取。
和Object.wait()
和Object.notify()
一样,当线程执行condition.await()
方法,线程必须已经获得了该重入锁(否则都不占用锁,哪来的释放锁让别的线程占用);同样,线程在执行condition.signal()
时,系统会在等待队列中唤醒一个线程,线程一旦唤醒,它会重新尝试获得与之相关联的锁,一旦成功则继续执行。因此,执行signal()
方法后需要释放锁。
网友评论