【发布时间】:2019-09-29 10:45:32
【问题描述】:
我最近在一次采访中被问到这个问题。
给定以下代码,静态整数num 的最小和最大可能值是多少?
import java.util.ArrayList;
import java.util.List;
public class ThreadTest {
private static int num = 0;
public static void foo() {
for (int i = 0; i < 5; i++) {
num++;
}
}
public static void main(String[] args) throws Exception{
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new Task());
threads.add(thread);
thread.start();
}
for (int i = 0; i < 5; i++) {
threads.get(i).join();
}
// What will be the range of num ???
System.out.println(ThreadTest.num);
}
}
class Task implements Runnable {
@Override
public void run() {
ThreadTest.foo();
}
}
我告诉他们最大值是 25(如果没有竞争条件),最小值是 5(如果每次迭代中所有线程之间都存在竞争条件)。
但面试官说最小值甚至可以低于 5。
这怎么可能?
【问题讨论】:
-
线程 1 在它的第一次迭代 (
i == 0) 中读取num == 0,然后所有其他线程都做他们的事情,除了线程 2,它只进行了前 4 次迭代。然后线程1恢复,将0递增到1并存储它,线程2在最后一次迭代中读取1,线程2在最后一次迭代中读取这个1,线程1完成剩下的工作,线程2递增@ 987654329@ 到2并终止。不确定它是否可以低于2。 -
对此的诚实回答是:这并不重要。存在数据竞赛,因此您无法有效地依赖它所做的任何事情。这只是错误的代码。
-
添加
volatile将使该程序顺序一致,因此从VM 的角度来看没有“竞争”。 -
@JohannesKuhn
num++不是原子的,所以它甚至不适用于volatile。 -
你有没有问过面试官:这怎么可能?
标签: java multithreading race-condition