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型作为条件判断,可能会出来读取出值后,值又被改变了的情况,这可能会导致执行本以不该被执行的代码。

  • 相关阅读:
    用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理
    jenkins持续集成:jenkins+SVN
    Linux基础一:Linux的安装及相关配置
    jenkins持续集成:构建多个job同时执行
    jenkins持续集成:定时构建语法
    Nginx详解二十九:基于Nginx的中间件架构设计
    Nginx详解二十八:Nginx架构篇Nginx+Lua的安全waf防火墙
    Nginx详解二十七:Nginx架构篇之安全篇
    Nginx详解二十六:Nginx架构篇之性能优化
    Nginx详解二十五:Nginx架构篇之Nginx常见的问题
  • 原文地址:https://www.cnblogs.com/qyit/p/14708346.html
Copyright © 2011-2022 走看看