Java:防止另一个线程获得控制权,直到第一个线程中的特定命令被执行



我有一个简单的并发代码,可以递增共享变量。

两个线程将计数器分别递增 10,000,000 次并打印结果。

它工作正常(争用条件通过增量方法中的synchronized解决(。

但是,在线程 A 完成递增后,线程 B 在线程 A 有机会打印其结果(应为 10,000,000(之前开始递增。我可以通过让线程 B 在开始自己的增量之前休眠 3 秒来解决它:

public class DogLatch {
private static Counter counter = new Counter();
public static void main(String[] args) throws Exception {
Thread a = new Thread(new A());
Thread b = new Thread(new B());
a.start();
b.start();
a.join();
b.join();
System.out.printf("counter: %,d", counter.getValue());
}
static class Counter  {
private int i;
public void increment()  {
synchronized (this)  {
i++;
}
}
public int getValue()  {return i;}
public void setValue(int i ) {this.i = i;}
}
static class A implements Runnable  {
@Override
public void run()  {
for (int i = 0; i < 10_000_000; i++) {
counter.increment();
}
System.out.println("A done: " + counter.getValue());
}
}
static class B implements Runnable  {
@Override
public void run()  {
System.out.println("Go to school");
System.out.println("Walk dog");
try  {
Thread.sleep(5000);
}
catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < 10_000_000; i++) {
counter.increment();
}
System.out.println("B done: " + counter.getValue());
}
}
}

会打印

Go to school
Walk dog
A done: 10000000
B done: 20000000
counter: 20,000,000

但是,如果我拒绝B

static class B implements Runnable  {
@Override
public void run()  {
System.out.println("Go to school");
System.out.println("Walk dog");
for (int i = 0; i < 10_000_000; i++) {
counter.increment();
}
System.out.println("B done: " + counter.getValue());
}
}

我得到

Go to school
Walk dog
A done: 17368068
B done: 20000000
counter: 20,000,000

输出。有没有办法在显示A done: 10000000B done: 10000000的地方实现正确的输出,而无需在B中诉诸Thread.sleep()

实际上,您的程序并没有真正执行太多并发处理。 您在线程 B 中等待 5 秒,而线程 A 增加到 10,000,000,然后 B 唤醒并继续。

如果您只是在单个线程中一个接一个地启动它们,则结果就是这样。

但是你知道它工作正常,因为最终结果总是 20,000,000 没有 sleep 语句。

如果您强制交替,您将失去使用线程的好处。 事实上,A 打印出不同的值,但最终计数是 20,000,000,这表明它工作得很好!

最新更新