用户级和内核级线程中的并发性。为什么产出不同?

时间:2012-09-13 01:57:37

标签: c multithreading

我开始学习线程了,现在我开始讨论本书让我误解了用户级和内核级线程。

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

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

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。

然而,这本书说输出是不同的,或者由于干预可能会有不同的输出,有人可以告诉我为什么吗?

3 个答案:

答案 0 :(得分:2)

在第一种情况下,它不是创建线程,而是分支进程(查找fork()函数的描述)。分叉进程有自己的内存,从父进程复制,因此减少子进程中的数字的结果将不会影响父进程。父进程中打印号的结果为1。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

在线程情况下,由于可能的数据竞争,可能会获得1或甚至-1作为最终值。由于无法保证在线程1完成后线程2将被启动,反之亦然,如果没有正确的同步,两个线程可能会在大约相同的时间开始并看到0的初始值。然后,根据哪个线程完成第二个,该值将是1-1而不是0。为了避免这种情况,必须使用关键部分或原子输入/减量之类的同步习语。