Ana*_*ria 0 java multithreading locking locks
在旧的同步块中,我们使用相同的对象进行同步,还使用了等待和通知方法。所以他们都可以引用同一个锁。说得通。
那么当我使用类 ReentrantLock 时,为什么我不能也使用相同的变量来调用lock、unlock以及await和signal?为什么我需要创建额外的 Condition 变量?
也就是说,为什么我需要这样做:
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
void doSomething() {
lock.lock();
//some code
condition.await();
//some code
lock.unlock();
}
Run Code Online (Sandbox Code Playgroud)
而不是这样:(这种类型的编码不会更合乎逻辑)?
Lock lock = new ReentrantLock();
void doSomething() {
lock.lock();
//some code
lock.await();
//some code
lock.unlock();
}
Run Code Online (Sandbox Code Playgroud)
编辑:来自文档:一个 Condition 实例本质上绑定到一个锁。 为什么要这样设计?为什么不只有一个 Lock 类型的变量,它会有 await 和信号方法?
的分离Lock
,并Condition
可以让你有一个以上的Condition
每Lock
,这是由记录Condition
:
Condition
通过将Object
监视器方法 (wait
,notify
和notifyAll
)与任意实现的使用结合起来,将监视器方法 ( ,和) 分解为不同的对象,以产生每个对象具有多个等待集的效果 [强调]Lock
。
并且Lock
:
[
Lock
实现]允许更灵活的结构,可能具有完全不同的属性,并且可能支持多个关联Condition
对象 [强调]。
有了这种能力,您可以执行以下操作:
import java.util.Objects;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Stack<E> {
private final Lock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final Object[] elements;
private int size;
public Stack(int capacity) {
elements = new Object[capacity];
}
public E pop() throws InterruptedException {
lock.lockInterruptibly();
try {
while (size == 0) {
notEmpty.await();
}
@SuppressWarnings("unchecked")
E element = (E) elements[--size];
elements[size] = null;
notFull.signal();
return element;
} finally {
lock.unlock();
}
}
public void push(E element) throws InterruptedException {
Objects.requireNonNull(element);
lock.lockInterruptibly();
try {
while (size == elements.length) {
notFull.await();
}
elements[size++] = element;
notEmpty.signal();
} finally {
lock.unlock();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法有两个好处:
Condition
才会收到信号。signalAll()
,这意味着只有一个线程被唤醒。这是同一个Stack
类,但使用synchronized
:
import java.util.Objects;
public class Stack<E> {
private final Object lock = new Object();
private final Object[] elements;
private int size;
public Stack(int capacity) {
elements = new Object[capacity];
}
public E pop() throws InterruptedException {
synchronized (lock) {
while (size == 0) {
lock.wait();
}
@SuppressWarnings("unchecked")
E element = (E) elements[--size];
elements[size] = null;
lock.notifyAll();
return element;
}
}
public void push(E element) throws InterruptedException {
Objects.requireNonNull(element);
synchronized (lock) {
while (size == elements.length) {
lock.wait();
}
elements[size++] = element;
lock.notifyAll();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在请注意,每个线程都必须等待相同的“条件”,并且每当发生任何事情时都会通知每个等待的线程。您必须通知所有等待的线程,因为您无法更好地控制通知哪些线程。
归档时间: |
|
查看次数: |
126 次 |
最近记录: |