原文链接:再论int变量赋值的原子性
<p>http://bbs.chinaunix.net/thread-1805189-1-1.html</p>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
struct STRU
{
char a;
int b;
}__attribute__((packed));
struct STRU v;
void threadfun1(void)
{
int i = 0;
while(1)
{
if(i%2 == 0)
{
v.b = 0x55555555;
}
else
{
v.b = 0xaaaaaaaa;
}
i++;
}
}
void threadfun2(void)
{ int i;
while(1)
{
i = v.b;
if((i != 0x55555555) && (i != 0xaaaaaaaa))
{
printf("v.b = %x\n", i);
}
}
}
void main(void)
{
pthread_t tidFun1;
pthread_t tidFun2;
pthread_create(&tidFun1, NULL, threadfun1, NULL);
pthread_create(&tidFun2, NULL, threadfun2, NULL);
while(1)
{
sleep(5);
}
}
可以看到,对变量v.b的一个int赋值被分成了多条汇编语句,在目标机上运行,打印结果为以下多种结果
v.b = 55aaaaaa
v.b = 555555aa
v.b = aa555555
v.b = aaaa5555
......
由此可见,至少在arm9的CPU上,在非内存对齐的情况下,存在一个线程对全局的int变量赋值没有完成而被另一个线程读走,从而导致未知后果的可能性。
如果是在X86上又会如何?
以下是在X86上的汇编代码:
由上看到,X86对这种字节对齐的int变量也是只用了一条movl语句进行赋值,所以不会存在赋值到一半被另一个线程读走的情况,通过运行实验程序也证明了这个问题。
最后,虽然题目是“再论int变量赋值的原子性”,但如果其内容能达到前一帖子的百分之一二有用,我就心满意足了