我在阅读一本教材时发现了这个问题。下面也给出了解决方案。我不理解最小值为2的原因。为什么一个线程不能读取0,其他所有线程都执行并写入1呢?而且无论是1还是2,最后写入的线程仍然必须完成自己的循环吗?
int n = 0;
int main(int argc, char **argv) {
for (i = 0; i < 5; i++) {
int tmp = n;
tmp = tmp + 1;
n = tmp;
}
return 0;
}
如果这个应用程序只有一个线程运行,那么预期的最终输出应该是5。如果5个线程并行运行相同的循环,n能够达到的最大和最小值是什么?最大值很明显是25,因为来自5个线程的5次增量。然而,对于最小可能的值进行推理会更加困难。提示:n可以小于5,但你需要自己弄清楚原因。
解决方案:
使用五个线程运行这个五次迭代的循环,且没有保护措施防止并发访问,n能够达到的最低值为2。从最终结果反向工作时,理解如何达到这个结果最容易了。为了得到最终输出为2,一个线程必须从n中读取到1的值,将其加1,然后写入2。这意味着另一个线程写入了1,这意味着它也最初读取了0(这也是n的起始值)。这解释了5个线程中的两个线程的行为。然而,为了使这种行为发生,其他三个线程的结果必须被覆盖。有两种有效的执行方式。要么1)所有三个线程在第一个线程读取零并写入一之间开始并完成执行,要么2)所有三个线程在最后一个线程读取一并写入二之间开始并完成执行。这两种执行顺序都是有效的。