• [转]线程安全 c/c++


    转自 http://www.cppblog.com/ivenher/articles/15815.html

    对于多线程编程,很多人概念不清,写代码的时候要么是处处加锁,影响性能不说,还容易莫名其妙的死锁,还有人对多线程敬而远之。

    所以学习多线程编程最重要的不是学习API,而是理解什么才是多线程安全的代码

    从例子说起

     1 #include <windows.h>
     2 #include <process.h>
     3 
     4 long global1 = 0;
     5 volatile long global2 = 0;
     6 
     7 class MyClass
     8 {
     9 public:
    10     MyClass() : m(0)
    11     {
    12         ++m;
    13     }
    14 
    15     int fun(int v)
    16     {
    17         return m+v; //-----------9
    18     }
    19 
    20     void set(int v)
    21     {
    22         m = v;   //-------------10
    23     }
    24     int m;
    25 };
    26 
    27 MyClass global_object; //-------------8
    28 
    29 unsigned int __stdcall thread_fun1(void *param)
    30 {
    31     static int static2 = 0;
    32     static MyClass static_object; //--------6
    33     int local1 = 0;
    34     
    35     ++local1;     //-------1
    36     ++static2;    //-------2
    37     ++global1;    //-------3
    38     ++global2;    //-------4
    39     InterlockedIncrement(&global1); //--------5
    40 
    41     local1 = global_object.fun(local1); //----------7
    42 
    43     global_object.set(local1); //---------------11
    44 
    45     return 0;
    46 }
    47 
    48 
    49 unsigned int __stdcall thread_fun2(void *param)
    50 {
    51     ++global1;    //-------3
    52     ++global2;    //-------4
    53     InterlockedIncrement(&global1); //--------5
    54 
    55     global_object.set(1); //-----------11
    56     return 0;
    57 }
    58 
    59 
    60 int main()
    61 {
    62     HANDLE thread1 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 1
    63     HANDLE thread2 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 2
    64     HANDLE thread3 = (HANDLE)_beginthreadex(0,0,&thread_fun2,0,0,0); //thread 3
    65     
    66     WaitForSingleObject(thread1,INFINITE);
    67     WaitForSingleObject(thread2,INFINITE);
    68     WaitForSingleObject(thread3,INFINITE);
    69     
    70     return 0;
    71 }

    1.局部变量局部使用是安全的
    为什么?因为每个thread 都有自己的运行堆栈,而局部变量是生存在堆栈中,大家不干扰。
    所以代码1
    int local1;
    ++local1;
    是安全的

    2.全局原生变量多线程读写是不安全的
    全局变量是在堆(heap)中
    long global1 = 0;
    ++global2;
    ++这个操作其实分为两部,一个是读,另外一个是写
     mov         ecx,global
     add         ecx,1
     mov         global,ecx
    所以代码3处是不安全的

    3.函数静态变量多线程读写也是不安全的
    道理同2
    所以代码2处也是不安全的

    4.volatile能保证全局整形变量是多线程安全的么
    不能。
    volatile仅仅是告诫compiler不要对这个变量作优化,每次都要从memory取数值,而不是从register
    所以代码4也不是安全

    5.InterlockedIncrement保证整型变量自增的原子性
    所以代码5是安全的

    6.function static object的初始化是多线程安全的么
    不是。
    著名的Meyer Singleton其实不是线程安全的
    Object & getInstance()

         static Object o;
         return o;
    }
    可能会造成多次初始化对象
    所以代码6处是不安全的

    7.在32机器上,4字节整形一次assign是原子的
    比如
    i =10; //thread1
    i=4; //thread2
    不会导致i的值处于未知状态,要么是10要么是4


    写好多线程安全的法宝就是封装,使数据有保护的被访问到
    安全性:

    局部变量>成员变量>全局变量

  • 相关阅读:
    微服务架构 ------ DockerCompose从安装到项目部署
    微服务架构 ------ Dockerfile定制镜像
    微服务架构 ------ Ubuntu下Docker的安装
    微服务架构 ------ 插曲 linux LVM磁盘扩容
    Ubuntu java环境变量配置
    微服务架构 ------ 插曲 hikari连接池的配置
    微服务架构 ------ 插曲 Mybatis逆向工程
    微服务架构 ------ 插曲 Linux平台 Ubuntu的安装
    微服务架构 ------ Day01 微服务架构优缺点
    k8s配置storage-class
  • 原文地址:https://www.cnblogs.com/yi-mu-xi/p/11400600.html
Copyright © 2020-2023  润新知