什么代码才是线程安全的

    技术2022-05-11  78

    #include <windows.h>#include <process.h>

    long global1 = 0;volatile long global2 = 0;

    class MyClass{public:    MyClass() : m(0)    {        ++m;    }

        int fun(int v)    {        return m+v; //-----------9    }

        void set(int v)    {        m = v;   //-------------10    }    int m;};

    MyClass global_object; //-------------8

    unsigned int __stdcall thread_fun1(void *param){    static int static2 = 0;    static MyClass static_object; //--------6    int local1 = 0;        ++local1;     //-------1    ++static2;    //-------2    ++global1;    //-------3    ++global2;    //-------4    InterlockedIncrement(&global1); //--------5

        local1 = global_object.fun(local1); //----------7

        global_object.set(local1); //---------------11

        return 0;}

    unsigned int __stdcall thread_fun2(void *param){    ++global1;    //-------3    ++global2;    //-------4    InterlockedIncrement(&global1); //--------5

        global_object.set(1); //-----------11    return 0;}

    int main(){    HANDLE thread1 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 1    HANDLE thread2 = (HANDLE)_beginthreadex(0,0,&thread_fun1,0,0,0); //thread 2    HANDLE thread3 = (HANDLE)_beginthreadex(0,0,&thread_fun2,0,0,0); //thread 3        WaitForSingleObject(thread1,INFINITE);    WaitForSingleObject(thread2,INFINITE);    WaitForSingleObject(thread3,INFINITE);        return 0;}

     

    1.局部变量局部使用是安全的为什么?因为每个thread 都有自己的运行堆栈,而局部变量是生存在堆栈中,大家不干扰。所以代码1int 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; //thread1i=4; //thread2不会导致i的值处于未知状态,要么是10要么是4

    写好多线程安全的法宝就是封装,使数据有保护的被访问到安全性:局部变量>成员变量>全局变量 


    最新回复(0)