共计 1133 个字符,预计需要花费 3 分钟才能阅读完成。
使用 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<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()
返回后需要重新获得锁。
此外,和 tryLock()
类似,await()
可以在等待指定时间后,如果还没有被其他线程通过 signal()
或signalAll()
唤醒,可以自己醒来:
if (condition.await(1, TimeUnit.SECOND)) {// 被其他线程唤醒
} else {// 指定时间内没有被其他线程唤醒
}
可见,使用 Condition
配合Lock
,我们可以实现更灵活的线程同步。
小结
Condition
可以替代 wait
和notify
;
Condition
对象必须从 Lock
对象获取。
正文完
星哥玩云-微信公众号