我试图用以下代码生成AAB AAB序列:
private static Semaphore semA = new Semaphore(2);
private static Semaphore semB = new Semaphore(0);
public static void main(String[] args) {
while(true) {
new P1A().start();
new P2B().start();
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
static class P1A extends Thread{
public void run() {
try {
semA.acquire();
System.out.print("A");
if(!semA.tryAcquire()) {
semB.release();
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
static class P2B extends Thread{
public void run() {
try {
semB.acquire();
System.out.print("B ");
semA.release(2);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
在这段代码中,最终结果是"A“。
据我所知,tryAcquire ()应该立即返回true或false,而不是延迟响应。我们如何解决这个问题呢?
发布于 2022-07-04 12:46:23
这主要是对您的问题的解释和分析方法--但我确实看到了您正在尝试的内容,并添加了一个简单的解决方案。
在遍历逻辑时最好使用表。请注意,P1A
和P2B
的执行顺序可能不同,因此这是一个序列--但我确信所有序列都会导致所描述的相同结果:
| P1A | semA | P2B | semB | Output |
| ----------- | ---- | ----------- | ---- | ------ |
| [1] started | | | | |
| | 2 | | 0 | |
| [1] acq A | 1 | | 0 | |
| | | | | A |
| [1] acqt A | 0 | | 0 | |
| | | [1] started | 0 | |
| | 0 | [1] blocked | 0 | |
| [1] end | 0 | | 0 | |
| [2] started | 0 | | 0 | |
| [2] blocked | 0 | | | |
| | 0 | [2] started | 0 | |
| | 0 | [2] blocked | 0 | |
无限的。
在每次迭代中启动新线程似乎只会使结果复杂化--而不是让每个线程自己永远循环。
因为semA
是用2个许可证初始化的,所以tryAcquire
将是成功的(true),因此!tryAcquire
是假的。
更新P1A
现在我看到了你们正在尝试的东西,我认为下面更直接地说明你们的方法。只需让P1A
这样做(保留P2B
原样):
public void run() {
if (semA.tryAcquire()) {
System.out.print("A");
} else {
semB.release();
}
}
关于主循环,我不能说它是错误的,除非它不会等待线程完成(连接),这只会导致混乱的结果。因此,要么join
两个线程(而不是睡眠),要么将永久循环移动到线程中。
https://stackoverflow.com/questions/72859353
复制相似问题