使用Condition

黑派客     最近更新时间:2020-01-16 05:28:49

795

使用ReentrantLock比直接使用synchronized更安全,可以替代synchronized进行线程同步。

但是,synchronized可以配合waitnotify实现线程在条件不满足时等待,条件满足时唤醒,用ReentrantLock我们怎么编写waitnotify的功能呢?

答案是使用Condition对象来实现waitnotify的功能。

我们仍然以TaskQueue为例,把前面用synchronized实现的功能通过ReentrantLockCondition来实现:

class TaskQueue {
    private final Lock lock = new ReentrantLock();    private final Condition condition = lock.newCondition();    private Queue<String> queue = new LinkedList<>();    public void addTask(String s) {
        lock.lock();        try {
            queue.add(s);
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }    public String getTask() {
        lock.lock();        try {            while (queue.isEmpty()) {
                condition.await();
            }            return queue.remove();
        } finally {
            lock.unlock();
        }
    }
}

可见,使用Condition时,引用的Condition对象必须从Lock实例的newCondition()返回,这样才能获得一个绑定了Lock实例的Condition实例。

Condition提供的await()signal()signalAll()原理和synchronized锁对象的wait()notify()notifyAll()是一致的,并且其行为也是一样的:

  • await()会释放当前锁,进入等待状态;

  • signal()会唤醒某个等待线程;

  • signalAll()会唤醒所有等待线程;

  • 唤醒线程从await()返回后需要重新获得锁。

展开阅读全文