gpt4 book ai didi

java - 使用等待和信号方法进行同步

转载 作者:行者123 更新时间:2023-12-01 22:39:50 25 4
gpt4 key购买 nike

使用手动等待和信号方法的信号量的java实现似乎不起作用。可能出了什么问题?

class Runner extends Thread implements Runnable{

public static int s=1;
private static int c;
private String tname;

Runner(){
tname=this.getName();
}
public void wait(int s){
while(s==0)
System.out.println(tname+" Waiting; s = "+s);
s--;
System.out.println(tname+" Wait over; s = "+s);
}

public void signal(int s){
s++;
System.out.println(tname+" Signalled; s ="+s);
}

public void run(){
wait(s);
//critical section begin
go();
//critical section end
signal(s);
}

public void go(){
int f=10;
while(f-->0){
c++;
System.out.println(tname+" : Counter = "+c);
}
}

}

public class wns{
public static void main(String[] args){
Runner t1=new Runner();
Runner t2=new Runner();
t1.start();
t2.start();
}
}

我在 Ubuntu 14.04 LTS 上运行它并得到了意外的输出。输出

Thread-1 Wait over; s = 0
Thread-0 Wait over; s = 0
Thread-0 : Counter = 2
Thread-0 : Counter = 3
Thread-0 : Counter = 4
Thread-0 : Counter = 5
Thread-0 : Counter = 6
Thread-0 : Counter = 7
Thread-0 : Counter = 8
Thread-0 : Counter = 9
Thread-0 : Counter = 10
Thread-0 : Counter = 11
Thread-0 Signalled; s =2
Thread-1 : Counter = 1
Thread-1 : Counter = 12
Thread-1 : Counter = 13
Thread-1 : Counter = 14
Thread-1 : Counter = 15
Thread-1 : Counter = 16
Thread-1 : Counter = 17
Thread-1 : Counter = 18
Thread-1 : Counter = 19
Thread-1 : Counter = 20
Thread-1 Signalled; s =2

即使 s 增加一次,其值也将变为 2。同样,当递减时,它再次变为 0,对同步完全没有影响。有人可以解释一下这里到底发生了什么吗?

最佳答案

两个线程都没有在等待。

两个线程大致同时进入wait()方法。两个线程大致同时检查是否 s == 0。两个线程几乎同时判定 s 确实等于 0。然后,两个线程大致同时递减 s。减量不是原子操作,并且两个线程同时尝试减量,因此可能只有一个减量实际上有效。 (因此在两者都调用减量后 s 为 0)。然后两个线程同时调用 signal。两个线程大致同时调用增量运算符。这次两个增量都发生了,因此 s 现在是 2。

真正的信号量和互斥体通常需要特殊的处理器调用来执行原子测试和设置操作。 Java 不允许您访问该操作(尽管它的同步机制肯定在幕后使用它),因此,如果不使用某种 Java 锁定机制(例如同步),您就无法编写自己的信号量类。

编辑:我在一件事上错了。 Java 确实允许使用位于 java.util.concurrent.atomic 包中的原子原语包装器(例如 AtomicInteger)访问compareAndSet 方法。您可以使用它们来创建自己的信号量,而无需使用synchronized 关键字。

示例:为了让大家明白这一点,如果 s 是 AtomicInteger,您可以将 while 循环替换为:

boolean waiting = true;
while(waiting) {
int stableSValue = s.get();
if(stableSValue == 0) {
System.out.println("Waiting. S was 0");
} else {
if(s.compareAndSet(stableSValue, stableSValue-1)) {
System.out.println("Wait done.");
waiting = false;
} else {
System.out.println("Optimistic locking failure. Trying again.");
}
}
}

关于java - 使用等待和信号方法进行同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26341261/

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