#include <stdio.h>
int num = 0;
int main(int argc, char*argv[]){
int pid;
pid = fork();
printf("%d", num);
if(pid == 0){ /*child*/
num = 1;
}else if(pid > 0){ /*parent*/
num = 2;
}
printf("%d", num);
}
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么可能的输出是0102或0012或0201或0021.
这是我认为它应该产生的东西.它命中第一个printf语句,无论先执行什么子项或父项,num都没有被修改,所以首先是0.那么接下来是1或2,然后执行下一个过程,所以再次从0开始(从父项复制),然后再次从1或2开始.所以可能的输出应该是:
0101或0102或0201或0202
Sam*_*ard 10
在父项和子项中,第一项的num为0 printf.在父和子中,打印0,然后打印另一个值.在父进程中,另一个值为2.在子进程中,另一个值为1.
但是,需要注意的重要一点是,虽然每个进程都有强制订单,零必须在另一个数字之前打印,但两个进程相对于彼此的打印没有限制.
这是一个真实的比喻:假设我的同事和我每个人同时离开工作,停在杂货店,然后到家.我知道在我回家之前我在商店,我们知道他在他家之前就在杂货店.但我们不知道谁先在杂货店,或者谁先在家.我们每个人都可以在同一时间到达杂货店,然后每个人大约在同一时间到家,或者他可能会被推迟,我甚至在他去商店之前就去了杂货店和家.
不会发生的事情是不止一次打印1或2.虽然在fork返回之后我们有两个进程在概念上同时运行,并且它们的事件相对于彼此的时间是未指定的,但是每个进程中的事件顺序都是明确定义的.每个进程num在再次打印之前将设置为1或2,并且因为fork被定义为在子级中返回0而子级中的子级pid,它们将各自设置为不同的值.
实际上,还有另一个合理的输出:00.如果fork无法创建新进程,则返回-1.在这种情况下,程序将打印0,if并且else ifs将失败,因为-1既不是0也不是大于0,num没有改变,程序0再次打印.
如果你想学习很多关于C程序中效果排序的定义,搜索的关键词是"序列点".在这个程序中它是相当简单的(除了我们一次运行两个副本的事实),但它有时可能不那么明显.
小智 9
这不是问题所在fork().这是printf()因为printf()被缓冲.通常,缓冲区在最后遇到换行符时会被刷新,'\n'.但是,由于您省略了这一点,缓冲区的内容会保留并且不会被刷新.最后,两个进程(原始进程和子进程)将具有0或1的输出缓冲区.当它最终被刷新时,你会在两个进程中看到这一点.
添加fflush(stdout);后printf()尝试.