gpt4 book ai didi

java - 创建一个模拟信号量的类,但允许的数量不得超过0

转载 作者:行者123 更新时间:2023-12-03 13:02:06 25 4
gpt4 key购买 nike

我遇到了一个使用信号量设计队列的问题,以便所有获取该信号的线程都必须等待,直到某个线程释放它们为止。但是这里要注意的是,如果在没有线程等待的情况下调用release,那么它不会像真正的信号灯那样有任何效果,在实际的信号灯中将添加额外的许可。我开始尝试这样的事情:

public class QueueOfThreads {

private Semaphore valve = new Semaphore(0);
volatile int count = 0;


public void acquire() throws InterruptedException {
synchronized(this) {
count++;
}
valve.acquire();
}

public void release() {
synchronized(this) {
if(count > 0) {
valve.release();
count--;
}
else {
System.out.println("will not release since no thread is waiting");
}
}
}

}
但是我可以看到这是错误的,因为如果在 count++之后抢占了一个线程,则可以在获取之前调用该版本。
我花了很多时间试图找到一种方法,以确保在任何发行版之前至少调用了一次获取。但是我总是会遇到同样的问题,在获取信号量之后,由于当前线程将处于等待状态,因此我无法向其他线程发出有关获取信号量的信号。但是,如果我在获取信号量之前发出信号,则可以在实际获取信号量之前抢占线程。
请让我知道是否可以编写这样的类(class)以及如何进行?
这个问题来自艾伦·B·唐尼(Allen B. Downey)在名为“信号量小书”的书中的评论,其中提到:
“信号量也可以用于表示队列。在这种情况下,初始值为0,通常编写代码,以便除非有线程等待,否则不可能发信号,因此信号量的值永远不会积极的。”

最佳答案

您可以利用Object.notify()释放一个等待线程,如果有的话:

public class QueueOfThreads {

public synchronized void acquire() throws InterruptedException {
wait();
}

public synchronized void release() {
notify();
}
}
但是,这仅适用于没有虚假唤醒的JVM。
如果可能发生虚假唤醒,则实现会更加复杂:
public class QueueOfThreads {
int threadCount = 0;
boolean notified = false;

public synchronized void acquire() throws InterruptedException {
threadCount++;
do {
wait();
} while (!notified);
threadCount--;
notified = false;
}

public synchronized void release() {
if (threadCount==0) {
return;
}
notified = true;
notify();
}
}

关于java - 创建一个模拟信号量的类,但允许的数量不得超过0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63981682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com