多个线程访问一个变量

Joh*_*ohn 5 c multithreading concurrentmodification

我在正在阅读的教科书中发现了这个问题.解决方案也在下面给出.我无法理解最小值是多少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;
}
Run Code Online (Sandbox Code Playgroud)

如果单个线程运行此应用程序,您可能希望最终输出为5.如果5个线程并行运行相同的循环,该怎么办?n可能具有的最大和最小值是多少?最大的应该是selfevident:25,从5个线程增加5个.然而,关于最小可能值的推理更加困难.提示:n可以小于5,但是由你决定原因.

解:

由于五个线程运行此五次迭代循环并且没有并发访问的保护,因此n可以达到的最低值是两个.从最终结果向后工作时,了解如何达到此结果是最简单的.对于最终输出为2,线程必须从n读取值1,递增它,然后写入2.这意味着另一个线程写了一个,暗示它最初也读为零(这也是n的起始值).这解释了五个线程中的两个线程的行为.但是,要发生此行为,必须覆盖其他三个线程的结果.两个有效的执行可以实现这一点.要么1)所有三个线程开始并在第一个线程读取零和写入一个之间完成执行,或者2)所有三个线程开始并在最终线程读取一个和写入两个之间完成执行.两个执行顺序都有效.

Ark*_*kku 4

假设每个线程都有一个本地线程i(即,无论如何每个线程都会运行 5 次迭代),让我们尝试得到 1 作为结果。这意味着最后一个写入值的线程必须n第五次迭代时读取 0。发生这种情况的唯一方法是,如果在该线程的第五次迭代开始时尚未有任何线程写入n,但要使该线程处于第五次迭代,该线程本身必须已写入n,因此这是不可能的。

\n\n

因此,最小可能的结果是 2,这可能会发生,例如,如下所示:最后一个写入的线程n已完成 4 次迭代,然后另一个线程写入 1,最后一个线程在第 5 次迭代开始时读取 1,所有其他线程在最后一个线程之前完成所有迭代,最后最后一个线程完成其第五次迭代,写入 2。

\n\n

免责声明:我正在回答有关多线程 \xe2\x80\x93 的概念问题,正如其他人指出的那样,如果按原样使用所提供的 C 代码,缺乏原子性可能会导致未定义的行为和任意结果。根据问题的 \xe2\x80\x9cself-evident\xe2\x80\x9d 最大数字情况,我猜测教科书的作者要么没有意识到这一点,要么正在使用类似 C 的伪代码来说明这个概念。如果是前者,那么正确的答案是这本书是错误的,但我认为后一种情况的答案也是有教育意义的。

\n

  • 免责声明:我正在回答有关多线程的概念问题 - 正如其他人指出的那样,写入的非原子性可能会导致未定义的行为和任意结果。基于问题的“不言而喻”的最大数字案例,我猜测教科书的作者要么没有意识到这一点,要么正在使用类似 C 的伪代码来说明这个概念。 (2认同)