0

我开始学习线程,现在我明白这本书让我对用户级和内核级线程感到困惑。

这本书非常强调差异并提出了一个问题,说以下两个相似代码的输出是不同的,但是(据我所知),它们的输出对我来说似乎是相同的。

第一个是关于用户级线程:

int number = 0;
int main() {
fork()
if it is child {number--, return 0}
if it is parent {number++, wait till child return, print number}}

我的分析是由于 number-- 和 number++ 只需要执行一次,并且执行完这两次后会打印输出,所以输出必须为 0。

第二种情况是关于内核级线程:

int number = 0;
t1() {number--}
t2() {number++}
main() {
    createThread(pass t1)
    createThread(pass t2)
    wait till both complete
    print number
}

在这种情况下,同样的事情,内核创建了两个线程,一个 --,另一个 ++,所以它们都只需要执行一次。并且结果必须再次为 0。

但是,书上说输出是不同的,或者由于干预可能会有不同的输出,谁能告诉我为什么?

4

3 回答 3

2

在第一种情况下,它不是创建线程,而是分叉一个进程(查看 fork() 函数的描述)。分叉的进程有自己的内存,是从父进程复制过来的,所以子进程中递减数字的结果对父进程没有影响。在父进程中打印数字的结果将为 1。

于 2012-09-13T05:17:44.030 回答
1

即使您编写了一条指令i++,或者i--它可能被翻译成机器语言中的多条指令。如果您使用的是内核线程,这两个计算可能会在不同的内核上运行,每个内核都会缓存i. 在这种情况下,实际写入内存的结果是未定义的,因为硬件和编译器假定没有人在背后修改数据。

于 2012-09-13T02:05:39.213 回答
0

在线程的情况下,由于可能的数据竞争,有可能获得1甚至作为最终值。-1由于无法保证线程 2 将在线程 1 完成后启动,反之亦然,因此如果没有适当的同步,两个线程可能会在大约同时启动并看到 的初始值0。然后根据哪个线程第二个完成,该值将是1或者-1而不是0. 为了避免这种情况,必须使用诸如临界区或原子增量/减量之类的同步习语。

于 2012-09-13T10:10:27.940 回答