如何锁定一系列方法,以便其他线程调用那些相同的方法应该等待?
How to lock a sequence of methods, such that other thread call those same method should be waiting?
假设有一个线程,它有一系列的方法要执行:
public void task(){
method();
method();
method();
method();
}
我想锁定整个序列。也就是说,当 task()
正在执行时,我不希望其他线程执行相同的 method()
而是等到整个 task()
完成。需要什么样的锁?
您需要某种共享锁,并将其引用传递给需要执行该序列的所有线程。
例如,在 class 上创建一个 public static final ReentrantLock LOCK = new ReentrantLock();
,其中包含 task() 方法,并在方法 task() 的开头写入 LOCK.lock();
和 LOCK.unlock();
在末尾。现在,所有通过 task() 方法的线程都将尝试获取锁,如果已经被占用,它将阻塞它们。
您可以使该任务 同步:
public synchronized void task() {
method();
method();
method();
method();
}
这将防止其他线程在同一对象上调用相同的 task()
方法,包括该对象上的其他 synchronized
方法。您可以使用显式 synchronized
语句进行更多控制,例如
public void task() {
synchronized (this) { // or another object
method();
method();
method();
method();
}
}
或使用您自己的 Lock 实例:
private final ReentrantLock lock = new ReentrantLock();
public void task() {
lock.lock(); // block until lock is released
try {
method();
method();
method();
method();
} finally {
lock.unlock();
}
}
如果您想让所有 method()
调用都不是 运行 同时,只需将相同的机制应用于 method()
声明:
public synchronized void method() // or one of the other two options
如果将这三种机制中的一种应用于 task
和 method
,您将确保调用 task()
的线程将完成所有 method()
调用顺序并防止其他线程同时调用任何 method()
。 synchronized
和 ReentrantLock
都允许同一个线程多次获得相同的 lock/monitor(嵌套锁)。
最后,如果你想允许对 method()
的多个并行调用,但只是在执行 task()
时不允许,你需要一个共享锁或 read-write 锁(参见 ReentrantReadWriteLock).
这可能是一个选项,但可能不是最好的。您可以这样修改 method()
的签名:
public void method(int serialExecutionCount) {
synchronized(this) {
for (int i = 0; i < serialExecutionCount; i++) {
// body of your method()
}
}
}
现在,您的 task()
方法将如下所示:
public void task() {
method(4);
}
现在,如果您像这样从其他线程调用它:
method(1);
它将等待 task()
方法的调用线程完成前 4 个方法调用。
假设有一个线程,它有一系列的方法要执行:
public void task(){
method();
method();
method();
method();
}
我想锁定整个序列。也就是说,当 task()
正在执行时,我不希望其他线程执行相同的 method()
而是等到整个 task()
完成。需要什么样的锁?
您需要某种共享锁,并将其引用传递给需要执行该序列的所有线程。
例如,在 class 上创建一个 public static final ReentrantLock LOCK = new ReentrantLock();
,其中包含 task() 方法,并在方法 task() 的开头写入 LOCK.lock();
和 LOCK.unlock();
在末尾。现在,所有通过 task() 方法的线程都将尝试获取锁,如果已经被占用,它将阻塞它们。
您可以使该任务 同步:
public synchronized void task() {
method();
method();
method();
method();
}
这将防止其他线程在同一对象上调用相同的 task()
方法,包括该对象上的其他 synchronized
方法。您可以使用显式 synchronized
语句进行更多控制,例如
public void task() {
synchronized (this) { // or another object
method();
method();
method();
method();
}
}
或使用您自己的 Lock 实例:
private final ReentrantLock lock = new ReentrantLock();
public void task() {
lock.lock(); // block until lock is released
try {
method();
method();
method();
method();
} finally {
lock.unlock();
}
}
如果您想让所有 method()
调用都不是 运行 同时,只需将相同的机制应用于 method()
声明:
public synchronized void method() // or one of the other two options
如果将这三种机制中的一种应用于 task
和 method
,您将确保调用 task()
的线程将完成所有 method()
调用顺序并防止其他线程同时调用任何 method()
。 synchronized
和 ReentrantLock
都允许同一个线程多次获得相同的 lock/monitor(嵌套锁)。
最后,如果你想允许对 method()
的多个并行调用,但只是在执行 task()
时不允许,你需要一个共享锁或 read-write 锁(参见 ReentrantReadWriteLock).
这可能是一个选项,但可能不是最好的。您可以这样修改 method()
的签名:
public void method(int serialExecutionCount) {
synchronized(this) {
for (int i = 0; i < serialExecutionCount; i++) {
// body of your method()
}
}
}
现在,您的 task()
方法将如下所示:
public void task() {
method(4);
}
现在,如果您像这样从其他线程调用它:
method(1);
它将等待 task()
方法的调用线程完成前 4 个方法调用。