有两个并发进程指的是P1P1和P2P2,其代码如下。

(window.slotbydup=window.slotbydup || []).push({
id: '2014386',
container: s,
size: '234,60',
display: 'inlay-fix'
&&|&&0次下载&&|&&总232页&&|
您的计算机尚未安装Flash,点击安装&
阅读已结束,如需下载到电脑,请使用积分()
下载:70积分
0人评价4页
0人评价9页
1人评价40页
0人评价123页
0人评价147页
此文档归属以下专题
0人评价10个文档
所需积分:(友情提示:大部分文档均可免费预览!下载之前请务必先预览阅读,以免误下载造成积分浪费!)
(多个标签用逗号分隔)
文不对题,内容与标题介绍不符
广告内容或内容过于简单
文档乱码或无法正常显示
文档内容侵权
已存在相同文档
不属于经济管理类文档
源文档损坏或加密
若此文档涉嫌侵害了您的权利,请参照说明。
我要评价:
价格:70积分VIP价:56积分 上传我的文档
 下载
 收藏
粉丝量:29
该文档贡献者很忙,什么也没留下。
 下载此文档
操作系统习题课(期末)
下载积分:2000
内容提示:操作系统习题课(期末)
文档格式:PDF|
浏览次数:201|
上传日期: 13:57:21|
文档星级:
全文阅读已结束,如果下载本文需要使用
 2000 积分
下载此文档
该用户还上传了这些文档
操作系统习题课(期末)
关注微信公众号博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)编译出来(一般来讲)大概会是这么几步:
再读a (这个可能被编译器优化掉)
写到屏幕上
两个线程,[1]和[2]:
[1]写a // a =2
[2]写a // a = 3
[2]写到屏幕上 // 3_
[1]写到屏幕上 // 2_
先执行所有[1]再执行所有[2]就得到B了,不解释了。
[1]写a // a = 2
[2]写a // a = 3
就得到3_3_了,但如果没有再读a的步骤,就是_2_3或者_3_2了。
[1]写a // a = 2
[2]写a // a = 2
就得到2_2_了
++i不是原子操作
我怎么觉得都可能呢?
假设线程x和y同时执行,x和y可随时被抢占,a的初始值为1
y先执行++a,a为2;
y再执行printf,a入栈,在打印到终端之前切换到x
x执行++a,a为3;
x执行printf,输出3;再切换到y
y执行打印,输出2
x先执行++a,a为2;
x再执行printf,输出2;切换到y
y执行++a,a为3;
y执行printf,输出3;
x先执行++a,a为2;切换到y
y执行++a,a为3;
y执行printf,输出3;切换到x
x执行printf,输出3
类似C,a的初始值为0即可
这里关键有两点:
(1)两个线程可随时被抢占
(2)++a和printf不是原子指令,可随时被打断;特别注意函数printf,a作为参数压栈后,a再变化则不会影响输出(printf实际打印的是压栈的参数,是值拷贝的栈变量)
考点有++a是原子操作 不可被中断 printf为非原子操作 可被中断 还要考虑缓冲区的问题 还要考虑参数进栈顺序
第一个线程执行
a的进栈操作 但并为输出 此时a的值2保留在缓冲区中 发生中断
第二个线程执行
完整的printf操作 输出3 然后让出cpu 线程1继续 输出2
第一个线程执行至函数结束 输出2
然后线程二执行至函数结束
线程一执行
然后发生中断
线程二执行直至函数结束 此时输出3 让出cpu
与A的区别是函数的进栈顺序 此时为3
D就不理解了 已经初始化为1 哪里来的0
2、3情况:线程1读入值1,增加1,值2返回内存,显示2;然后,线程2读入值2,增加1,值3返回内存,显示值3。
3、2情况,根据对称性,与2、3情况相同。
2、2情况,线程1读入1后,线程2运行,读入1,然后线程1运行,增加1,值2返回内存,显示2,然后线程2运行,增加1,值2返回内存,显示2。(线程1、2可互换)
3、3情况:线程1读入1,增加1,值2返回内存,结果2显示前线程2运行,增加1,值2返回内存,显示3,然后线程1运行,从内存读入3,显示3。
3,3这3种情况都很好理解,我就不赘述了。
我来讲解一下为什么会输出2,2吧。
不知道朋友们有没有学过X86汇编,是这样的,你看a=a+1这一条语句,看起来是一条语句,实际上这条语句会被编译成大概3条指令的。
首先是先计算出a+1的值,那么就是:
(把a的值赋给寄存器al)
(寄存器al的值加1)
计算完a+1的值后,会再进行赋值,对应的指令是 :
a,al(把寄存器al里的值赋给变量a)
大概就是这样的一个过程,3条指令。
你想既然这样,第1个进程可能是执行到
刚好计算完a+1的值,还没给变量a赋值(这时al里保存的是2,a依然是1),CPU就转换到执行第2个进程了,第2个进程完成这3条指令后,a的值为2,输出2,然后又回到第1个进程,这时开始执行mov
a,al(把寄存器al里的值2赋给2),所以a的值为2,也输出2。
希望你们能看到我的观点,如果看不懂的话也没关系,简单地说就是:a=a+1这一句实际上执行是由很多条指令组成的。
多线程在操作一个全局变量时,
①首先每个线程都会将全局变量copy一份到线程自己的内存,内部操作副本;(此时全局变量值不变)
②再更新全局变量(全局变量值改变)。
③读取全局变量(改变后的),输出。
那么产生不同结果的原因就在于多个线程在①,②,③步的执行顺序;
如题:线程用A,B命名;
A复制a=1到线程内存中a1= 1,a1为a的副本;
a1= ++a; a1 = 2;
A更新a的值,a=2;
A读取a,并输出
B读取a的副本,a2位a的副本,a2=2;
a2 = ++a;a2 = 3;
B更新a的值,a=3;
B读取a,并输出
&&&&&&&因此
可能的输出结果为:2,3
A,B线程执行顺序相反,B先执行,输出2,A后执行输出3;
&&&&&&&因此
可能的输出结果为:3,2
在上述1.中
处A输出a值的操作
处,则A,B均输出3;
&&&&&&&因此
可能的输出结果为:3,3
A,B存在读取a(a=1时)的副本,此时,a1 = 1,a2 =1;
A,B操作副本之后,a1=2,a2=2;
A,B更新a的值
A,B读取a值,并输出,a=2;
此时,A,B的执行顺序不影响结果;
&&&&&&&因此
可能的输出结果为:2,2
个人理解,若有不对的地方,
,欢迎指正。
注意a=a+1, ,printf 都不是原子操作
可以理解为:
1. 从内存读取a
3. a值写入内存
4. 从内存读出a
5. a值压入printf栈
6. printf显示到屏幕
P1从内存读出a(a=1)
P1使a值+1,然后写入内存
P2从内存读出a(a=2)
P1从内存读出a,然后压入printf栈(预备打印,此后a的值改变不影响printf结果)(a=2)(3.4顺序可换)
P2使a值+1,然后写入内存(a=3)
P2从内存读出a,然后压入printf栈(预备打印,此后a的值改变不影响printf结果)(a=3)
P2 printf显示到屏幕(a=3)
P1 printf显示到屏幕(a=2)
P1从内存读出a(a=1),然后使a值+1,然后写入内存,然后读出并压入printf栈,显示到屏幕(a=2)
P2从内存读出a(a=2),然后使a值+1,然后写入内存,然后读出并压入printf栈,显示到屏幕(a=3)
P1从内存读出a(a=1),然后使a值+1,然后写入内存(a=2)
P2从内存读出a(a=2),然后使a值+1,然后写入内存(a=3)
P1从内存读出a,然后压入printf栈,显示到屏幕(a=3)
P2从内存读出a,然后压入printf栈,显示到屏幕(a=3)
P1从内存读出a(a=1)
P2从内存读出a(a=1)
P1使a值+1,然后写入内存,然后读出并压入printf栈(a=2)
P2使a值+1,然后写入内存,然后读出并压入printf栈(a=2)
printf显示
这题答案怎么又变成ABC了。。。
这题的关键在于C语言中 ++a 算不算原子操作吧。
我在网上看到有个博主编译出来不是原子的,但我用GCC 4.8.1编译出来的是原子操作。
所以这题是不是有点问题。
#include &stdio.h&
int main() {
int a = 0;
movl $0, 12(%esp)
addl $1, 12(%esp)
movl $0, %eax
.cfi_restore 5
.cfi_def_cfa 4, 4
.cfi_endproc
直接用addl+1了。
发现我错了,这是C语言代码,不是java代码,而我还用java的思路去解决。
对于C语言来说,++i是原子操作。
===& a = 1
===& a = 1
【2】a++,写a ===& a = 2
【2】输出a
【1】a++,写a ===& a = 2
【1】输出a
2 2怎么会是对的?输出至少有一个是3才对
3.3情况个人理解是两个线程同时读取a 的值,因为运算是在栈中进行的,两线程同时加载1同时运算出栈写回全局变量区,结果都是2
程序当中隐藏了两个读数据操作
1)从地址中读a , 然后才能对 a 加1操作,加操作后直接存储到对应地址
2)从地址中读a , 然后print
两个 “读 加 读 写” 过程交错进行可以得到不同的结果
正确答案到底是哪一个啊??求大神解答
printf不是原子操作所以选择A,++i不是原子操作有D
[1]:读到1,把1放入工作空间
[1]:执行++a,a =2,刷回共享空间
[2]:读到2,把2放入工作空间
[2]:执行++a,a =3,刷回共享空间
[1]:打印a=2;
[2]:打印a=3;
[1]:读取a=1,把1放入工作内存,执行++a,a=2,刷回共享内存a=2,
[2]:读取a=2,把2放入工作内存,执行++a,a=3,刷回共享内存a=3
[1]读取a=3,打印
[2]读取a=3,打印
1.注意自加和打印操作都不是原子操作; 2.要考虑编译优化
这道题你会答吗?花几分钟告诉大家答案吧!
扫描二维码,关注牛客网
下载牛客APP,随时随地刷题
京ICP备号-4
扫一扫,把题目装进口袋

我要回帖

更多关于 shell 多进程并发 的文章

 

随机推荐