再论int变量赋值的原子性

原文链接:再论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上的汇编代码:

  1. 08048444 <threadfun1>:
  2. 8048444: 55 push %ebp
  3. 8048445: 89 e5 mov %esp,%ebp
  4. 8048447: 83 ec 10 sub $0x10,%esp
  5. 804844a: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp)
  6. 8048451: 8b 45 fc mov 0xfffffffc(%ebp),%eax
  7. 8048454: 83 e0 01 and $0x1,%eax
  8. 8048457: 85 c0 test %eax,%eax
  9. 8048459: 75 0c jne 8048467 <threadfun1+0x23>
  10. 804845b: c7 05 15 97 04 08 55 movl $0x55555555,0x8049715
  11. 8048462: 55 55 55
  12. 8048465: eb 0a jmp 8048471 <threadfun1+0x2d>
  13. 8048467: c7 05 15 97 04 08 aa movl $0xaaaaaaaa,0x8049715
  14. 804846e: aa aa aa
  15. 8048471: 83 45 fc 01 addl $0x1,0xfffffffc(%ebp)
  16. 8048475: eb da jmp 8048451 <threadfun1+0xd>
复制代码


由上看到,X86对这种字节对齐的int变量也是只用了一条movl语句进行赋值,所以不会存在赋值到一半被另一个线程读走的情况,通过运行实验程序也证明了这个问题。

最后,虽然题目是“再论int变量赋值的原子性”,但如果其内容能达到前一帖子的百分之一二有用,我就心满意足了

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值