zoukankan      html  css  js  c++  java
  • C++中简单类型bool变量的原子性

    这个问题实际上跟平台有很大的相关性。我们可以从汇编来看。

    linux(x86)平台:

    int main()
    {
      bool f = true;
      if (f)
      {
        f = false;
      }
      return 0;
    }
    (gdb) list
    1    int main()
    2    {
    3      bool f = true;
    4      if (f)
    5      {
    6        f = false;
    7      }
    8      return 0;
    9    }
    (gdb) b 4
    Breakpoint 1 at 0x602: file ../src/Test.cpp, line 4.
    (gdb) r
    Starting program: /home/ubuntu/workspace/Test/Debug/Test 
    
    Breakpoint 1, main () at ../src/Test.cpp:4
    4      if (f)
    (gdb) disassemble 
    Dump of assembler code for function main():
       0x00005555555545fa <+0>:    push   %rbp
       0x00005555555545fb <+1>:    mov    %rsp,%rbp
       0x00005555555545fe <+4>:    movb   $0x1,-0x1(%rbp)
    => 0x0000555555554602 <+8>:    cmpb   $0x0,-0x1(%rbp)
       0x0000555555554606 <+12>:    je     0x55555555460c <main()+18>
       0x0000555555554608 <+14>:    movb   $0x0,-0x1(%rbp)
       0x000055555555460c <+18>:    mov    $0x0,%eax
       0x0000555555554611 <+23>:    pop    %rbp
       0x0000555555554612 <+24>:    retq   
    End of assembler dump.

    从以上代码可以看到,对bool型的赋值操作 movb $0x1,-0x1(%rbp) 和对bool型的比较操作 cmpb $0x0,-0x1(%rbp) 都是一条汇编指令,可以认为是原子操作。

    linux(arm)平台:

    1 int main()
    2 {
    3   bool f = true;
    4   if (f)
    5   {
    6     f = false;
    7   }
    8   return 0;
    9 }
    (gdb) list
    1
    2
    3       int main()
    4       {
    5         bool f = true;
    6         if (f)
    7         {
    8           f = false;
    9         }
    10        return 0;
    (gdb) b 6
    Breakpoint 1 at 0x4005ac: file test.cpp, line 6.
    (gdb) r
    Starting program: /home/ubuntu/workspace/test/test
    
    Breakpoint 1, main () at test.cpp:6
    6         if (f)
    (gdb) disassemble
    Dump of assembler code for function main():
       0x00000000004005a0 <+0>:     sub     sp, sp, #0x10
       0x00000000004005a4 <+4>:     mov     w0, #0x1                        // #1
       0x00000000004005a8 <+8>:     strb    w0, [sp,#15]
    => 0x00000000004005ac <+12>:    ldrb    w0, [sp,#15]
       0x00000000004005b0 <+16>:    cmp     w0, #0x0
       0x00000000004005b4 <+20>:    b.eq    0x4005bc <main()+28>
       0x00000000004005b8 <+24>:    strb    wzr, [sp,#15]
       0x00000000004005bc <+28>:    mov     w0, #0x0                        // #0
       0x00000000004005c0 <+32>:    add     sp, sp, #0x10
       0x00000000004005c4 <+36>:    ret
    End of assembler dump.

    从以上代码可以看到,对bool型的赋值操作 strb w0, [sp,#15] ,读取操作 ldrb w0, [sp,#15] 和比较操作 cmp w0, #0x0 均是原子操作。但是,与x86不同的是,在arm上,读取与比较是分开的。所以多线程编程时,以bool型作为条件判断,可能会出来读取出值后,值又被改变了的情况,这可能会导致执行本以不该被执行的代码。

  • 相关阅读:
    框架:Java-Spring Cloud
    DB-数据库:百科
    公司-风险投资公司-软银银行集团:百科
    百科-Java-API:POI
    组织:基金会
    un-解决方案-MSP(管理服务提供商):百科
    汉语-词语:金融
    DBS-MySQL:MYSQL获取自增ID的四种方法
    linux框架之ibus
    jQuery+CSS 简单代码实现遮罩层( 兼容主流浏览器 )
  • 原文地址:https://www.cnblogs.com/qyit/p/14708346.html
Copyright © 2011-2022 走看看