这是一些挑战
在假设加载和存储是原子的单处理器系统上,假设 x 初始化为 O,在两个线程都完成以下执行后,x 的所有可能值是多少?提示:您需要考虑如何将这段代码编译成机器语言。
对于 (int i = 0; i < 5; i++) : x = x + 1;
对于 (int j = 0; j < 5; j++) : x = x + 1;
这是一些挑战
在假设加载和存储是原子的单处理器系统上,假设 x 初始化为 O,在两个线程都完成以下执行后,x 的所有可能值是多少?提示:您需要考虑如何将这段代码编译成机器语言。
对于 (int i = 0; i < 5; i++) : x = x + 1;
对于 (int j = 0; j < 5; j++) : x = x + 1;
您问题中的两行中的每一行都代表一个单独的线程。由于共享变量x
没有受到保护,几乎任何事情都可能发生。你想出了哪些可能性?(否则我会觉得我只是在为你回答你的问题)
第二个提示:让 C 编译器通过向您展示一些示例来帮助您...
int x;
void f(void)
{
int i;
for (i = 0; i < 5; i++) x = x + 1;
}
(这是你的程序翻译成C)
gcc -S -fno-PIC t.c
(这是我必须在我的机器上输入才能获得可读程序集的内容)
_f:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $0, -12(%ebp)
jmp L2
L3:
movl _x, %eax
incl %eax
movl %eax, _x
leal -12(%ebp), %eax
incl (%eax)
L2:
cmpl $4, -12(%ebp)
jle L3
leave
ret
现在进行优化(在编译中添加选项 -O2):
_f:
movl _x, %eax
xorl %edx, %edx
pushl %ebp
movl %esp, %ebp
.align 4,0x90
L2:
incl %edx
incl %eax
cmpl $5, %edx
jne L2
movl %eax, _x
leave
ret
提示:你不需要考虑所有可能的序列,你只需要考虑最极端的情况。x 可能的最小值是多少?x 可能的最大值是多少?
当一个线程的负载总是发生在负载之后和另一个线程中的存储之前,会发生最小的情况。
当没有重叠的加载-修改-存储序列时,将出现最大情况。
这应该足够你现在解决问题的提示了。
每个线程将有 5 组指令:
LOAD X
INCREMENT X
STORE X
在每条指令之后,CPU 可以选择让执行另外两个线程。
well, most decent compilers will optimise that to x=10;
umm, 10. Enlighten me otherwise.