序列Java带有信号量
我正在尝试将Aabbaabb的序列归于无限,但我得到的是Aabbaaabb。 Java代码如下:
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.availablePermits() == 0) {
semB.release(2);
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
static class P2B extends Thread{
public void run() {
try {
semB.acquire();
System.out.print("B");
if(semB.availablePermits() == 0)
semA.release(2);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
根据我的代码,一旦打印了两次,它应该将线程p1a悬挂到线程P2B以进行两次运行。但是,尽管交通灯释放了2个座位,但我无法得到它...
您能帮我吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是您的代码中发生的事情:
aabbaaaabb ...
。在将线程标识符添加到打印语句中并在发布后添加其他日志记录允许整个运行看起来像这样(
println
使用而不是print
以获得更好的可读性):当然可以多种方法来解决这个问题(我假设不是假设不是最好的,但工作)可能是对目标状态的同步验证(信号量参考必须称为
final
):由于同步,每个线程到达内部如果有访问权限对于实际(“目标”)状态 - 在这种情况下,不可能进行并行修改。
上面的行为是a compare-and-swap(cas)操作 - 我们验证当前价值是否是我们期望的值,如果是的,我们会采取行动;否则,我们会跳过执行主体的
。 Semaphore实际上部分使用此机制(
smaphore.sync
内类),但是它会重新恢复增量直到成功(或溢出后抛出):我创建了 github存储库您可以在上面找到记录结果的代码( initialwithlogging ),带有注释的固定代码( initialfixedwithcomments )和一个重构代码,严格代表了无重复的抽象( SimplifiedSolution )。
Here's what is happening in your code:
AABBAAAABB...
.After adding thread identifiers to the print statements and adding additional logging after releasing permits the whole run looks like this (
println
used instead ofprint
for better readability):There may of course multiple ways of resolving that, one of which (I'd assume not the best, but working) could be a synchronized verification of the target state (Semaphore references have to be declared as
final
):Thanks to the synchronization, each thread that reaches the inner
if
has access to the actual ("target") state - no parallel modification is possible in this case.The behavior above is a compare-and-swap (CAS) operation - we verify if current value is a value we expect and if so, we act on it; otherwise we skip execution of the
if
body. Semaphore actually partially uses this mechanism underneath (Semaphore.Sync
inner class), but it retries the incrementation until successful (or throws after overflowing):I've created a GitHub repository where you can find the code for the logging result above (InitialWithLogging), a fixed code with comments (InitialFixedWithComments) and a refactored code that strictly represents the abstraction without duplication (SimplifiedSolution).