首页 > 试题广场 >

两个线程并发执行以下代码,假设a是全局变量,初始值是1,那么

[不定项选择题]
两个线程并发执行以下代码,假设a是全局变量,初始值是1,那么以下输出中()是可能的。
void foo ( )
{
  ++a;
  printf("%d",a);
}
  • 3_2_
  • 2_3_
  • 3_3_
  • 2_2_
A,就是根据++a操作是要分3步进行来分析,即读取a,对a进行加1,再对a写入内存。经过分析即可得到答案A
发表于 2015-07-11 21:08:17 回复(0)
感觉都有可能吧:
 ++不能认为是原子操作,a是全局变量,在内存中,则++a一般被分为从内存取a到寄存器、+、回写到内存三步,考虑到并发。
设两个线程,[1]和[2]:

A
[1]读a
[1]+1
[1]写a // a =2
[1]再读a
[2]读a
[2]+1
[2]写a // a = 3
[2]再读a
[2]写到屏幕上 // 3_
[1]写到屏幕上 // 2_
B

先执行所有[1]再执行所有[2]就得到B了。

C
[1]读a
[1]+1
[1]写a // a = 2
[2]读a
[2]+1
[2]写a // a = 3
[1]再读a
[2]再读a
...
就得到3_3_了,但如果没有再读a的步骤,就是_2_3或者_3_2了。

D
[1]读a
[2]读a
[1]+1
[2]+1
[1]写a // a = 2
[2]写a // a = 2

就得到2_2_了
发表于 2015-07-11 15:18:37 回复(3)

假设线程x和y同时执行,x和y可随时被抢占,a的初始值为1

A:3, 2

y先执行++a,a为2;
y再执行printf,a入栈,在打印到终端之前切换到x
x执行++a,a为3;
x执行printf,输出3;再切换到y
y执行打印,输出2

B:2 3

x先执行++a,a为2;
x再执行printf,输出2;切换到y
y执行++a,a为3;
y执行printf,输出3;

C:3 3

x先执行++a,a为2;切换到y
y执行++a,a为3;
y执行printf,输出3;切换到x
x执行printf,输出3

D:2 2

类似C, 执行++a操作但没有写回到内存

这里关键有两点:

  • (1)两个线程可随时被抢占
  • (2)++a和printf不是原子指令,可随时被打断;特别注意函数printf,a作为参数压栈后,a再变化则不会影响输出(printf实际打印的是压栈的参数,是值拷贝的栈变量)
发表于 2020-07-29 22:17:49 回复(0)
变量递增操作不是原子操作,单个线程对全局变量做增量操作分为3步: 1.从内存读入寄存器 2.在寄存器对变量值加1 3.把新值写回内存单元 4.打印内存单元中变量的值(暂把printf看做原子操作吧) 两个线程在并发执行且不做同步的情况下,各自三个步骤是可能有序串行的,可以退出4个选项的情况
发表于 2018-01-19 17:46:20 回复(1)
此题C选项,3_3从何而来? 首先根据此题,这两个线程应该只调用一次这个函数,那么说对于a的读,每个线程只读一次。 我们可以这么想,两个线程T1,T2要么同时读,则都读到的第一次a为1,可得结果,2_2;若有一先一后,则一个读到另一个的写回结果,必有2_3或者3_2;你如果说读更多次,那还可能是更大的数呢!
发表于 2017-06-26 16:04:16 回复(1)
A  线程并发执行 
编辑于 2015-07-15 17:49:07 回复(1)
d选项,同时读取到1,然后2个1同时加1,然后随便一个顺序写入,写入了2次2
发表于 2022-08-09 10:41:28 回复(0)

解析

假设线程x和y同时执行,x和y可随时被抢占,a的初始值为1

  • A:3, 2
    y先执行++a,a为2;
    y再执行printf,a入栈,在打印到终端之前切换到x
    x执行++a,a为3;
    x执行printf,输出3;再切换到y
    y执行打印,输出2

  • B:2 3
    x先执行++a,a为2;
    x再执行printf,输出2;切换到y
    y执行++a,a为3;
    y执行printf,输出3;

  • C:3 3
    x先执行++a,a为2;切换到y
    y执行++a,a为3;
    y执行printf,输出3;切换到x
    x执行printf,输出3

  • D:2 2
    类似C, 执行++a操作但没有写回到内存

这里关键有两点:
(1)两个线程可随时被抢占
(2)++a和printf不是原子指令,可随时被打断;特别注意函数printf,a作为参数压栈后,a再变化则不会影响输出(printf实际打印的是压栈的参数,是值拷贝的栈变量)

发表于 2020-08-12 22:28:13 回复(0)
A:3, 2
y先执行++a,a为2;
y再执行printf,a入栈,在打印到终端之前切换到x
x执行++a,a为3;
x执行printf,输出3;再切换到y
y执行打印,输出2

B:2 3
x先执行++a,a为2;
x再执行printf,输出2;切换到y
y执行++a,a为3;
y执行printf,输出3;

C:3 3
x先执行++a,a为2;切换到y
y执行++a,a为3;
y执行printf,输出3;切换到x
x执行printf,输出3

D:2 2
类似C, 执行++a操作但没有写回到内存

这里关键有两点:
(1)两个线程可随时被抢占
(2)++a和printf不是原子指令,可随时被打断;特别注意函数printf,a作为参数压栈后,a再变化则不会影响输出(printf实际打印的是压栈的参数,是值拷贝的栈变量)
发表于 2020-03-12 20:54:44 回复(0)
++a不是原子操作,printf更不是原子操作,两行代码之前也有可能被打断
发表于 2019-12-23 20:17:34 回复(0)
第二次遇到
发表于 2019-05-09 20:13:18 回复(0)
忘记读取的操作了
发表于 2019-02-20 14:47:21 回复(0)
++i和printf不都是愿子操作 ,只有bc
发表于 2017-04-16 08:52:18 回复(0)
A可能是从缓存里读取了,输出2的时候没从内存中取出a
“多任务环境下各任务间共享的标志应该加volatile;”
发表于 2017-03-13 16:16:26 回复(0)
printf 应该也不能认为是原子操作?
发表于 2017-02-15 00:51:50 回复(0)
d选项,同时读取到1,然后2个1同时加1,然后随便一个顺序写入,写入了2次2
发表于 2016-11-05 10:37:43 回复(0)
原来是个多选题,想了半天
发表于 2016-08-30 19:18:24 回复(0)
fyf头像 fyf
这题怎么做啊,完全没思路啊
发表于 2016-07-07 11:42:08 回复(0)
printf还有缓冲呢
发表于 2016-03-21 22:55:21 回复(1)