使用Condition

使用Condition

廖雪峰

资深软件开发工程师,业余马拉松选手。

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

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

答案是使用Condition对象来实现wait和notify的功能。

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

class TaskQueue {

private final Lock lock = new ReentrantLock();

private final Condition condition = lock.newCondition();

private Queue 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()返回后需要重新获得锁。

此外,和tryLock()类似,await()可以在等待指定时间后,如果还没有被其他线程通过signal()或signalAll()唤醒,可以自己醒来:

if (condition.await(1, TimeUnit.SECOND)) {

// 被其他线程唤醒

} else {

// 指定时间内没有被其他线程唤醒

}

可见,使用Condition配合Lock,我们可以实现更灵活的线程同步。

小结

Condition可以替代wait和notify;

Condition对象必须从Lock对象获取。

相关推荐

浅析电池的三大寿命
365beat中文版

浅析电池的三大寿命

📅 08-01 👁️ 2837
lol五星大厨塔姆有特效吗(英雄联盟五星大厨)
365平台怎么注册

lol五星大厨塔姆有特效吗(英雄联盟五星大厨)

📅 08-01 👁️ 4209
轻松激活你的12306会员账户
office365无法登录账号

轻松激活你的12306会员账户

📅 07-29 👁️ 7374
第8章:镜头照明
office365无法登录账号

第8章:镜头照明

📅 08-15 👁️ 4112
迷你世界转轴方块上放灯为什么不亮
365beat中文版

迷你世界转轴方块上放灯为什么不亮

📅 07-08 👁️ 5220
dnf雪人套属性选哪个
365beat中文版

dnf雪人套属性选哪个

📅 08-17 👁️ 7177
90后年薪大概有多少才算正常?有多少存款才不算拖后腿?
office365无法登录账号

90后年薪大概有多少才算正常?有多少存款才不算拖后腿?

📅 08-13 👁️ 8870
火影中天天为啥没中无限月读?看到这一幕,才明白天天最想要啥
腾讯公司的企业文化
office365无法登录账号

腾讯公司的企业文化

📅 07-19 👁️ 5884