zoukankan      html  css  js  c++  java
  • window下线程同步之(原子锁)

    原子锁:当多个线程同时对同一资源进行操作时,由于线程间资源的抢占,会导致操作的结果丢失或者不是我们预期的结果。

    比如:线程A对一个变量进行var++操作,线程B也执行var++操作,当线程A执行var++时,如果线程切换时间恰好是线程A将结果存在var变量之前,那么线程B继续执行var++;此时假设var值已经被线程B更新,这时轮流到线程A执行,线程A会将接着上次停止的点继续向下执行,这时B对var变量的更改将会被覆盖掉;原子锁是对单条操作指令进行原子保护,保证在同一时间,只能有一个线程对变量进行操作,以此确保数据的正确性.

    1、InterlockedIncrement:加1操作; 
    2、InterlockedDecrement:减1操作; 
    3、InterlockedExchangeAdd:加上“指定”的值,可以加上一个负数; 
    4、InterlockedExchange、InterlockedExchangePointer:能够以原子操作的方式用第二个参数的值来取代第一个参数的值;

    一般情况下,在多线程编程中如果对某一个变量的值进行改变的话,使用以上互锁函数确实比较方便,但有很多时候多线程间会操作更为复杂的东西
    比如对一个结构的赋值、对链表的插入与删除 等等,以上互锁函数不能满足要求,所以要使用更为高级的多线程间的同步技术!

    没有使用原子锁的情况:
    #include <Windows.h> 
    #include <iostream> 
    using namespace std;
    
    #define ThreadNum  2 
    #define CIRCLETIME 1000000 
    long g_loginCount = 0; 
    long g_value = 0;
    
    DWORD WINAPI ThreadProc1( __in  LPVOID lpParameter ) 
    { 
        for( int index=0; index<CIRCLETIME; index++ ) 
        { 
            g_loginCount++; 
        } 
        return 0; 
    }
    
    DWORD WINAPI ThreadProc2( __in  LPVOID lpParameter ) 
    { 
        for( int index=0; index<CIRCLETIME; index++ ) 
        { 
            g_loginCount++; 
        } 
        return 0; 
    }
    
    int main() 
    { 
        HANDLE handle[ ThreadNum ] = {0};
    
        handle[0] = CreateThread(NULL,0,ThreadProc1,NULL,0,NULL); 
        handle[1] = CreateThread(NULL,0,ThreadProc2, NULL,0 ,NULL );
    
        WaitForMultipleObjects(ThreadNum,handle,TRUE,INFINITE); 
        CloseHandle( handle[0] ); 
        CloseHandle( handle[1] );
    
        cout << "循环之后的值为: " << g_loginCount  << " " <<  g_value << endl; 
        return 0; 
    }

    运行2次结果如下:
    image

    image

    使用原子锁的情况:

    DWORD WINAPI ThreadProc2( __in  LPVOID lpParameter ) 
    { 
        for( int index=0; index<CIRCLETIME; index++ ) 
        { 
            g_loginCount++; 
            InterlockedIncrement( &g_value  ); 
        } 
        return 0; 
    }
    
    DWORD WINAPI ThreadProc1( __in  LPVOID lpParameter ) 
    { 
        for( int index=0; index<CIRCLETIME; index++ ) 
        { 
            g_loginCount++; 
            InterlockedIncrement( &g_value  ); 
        }         
        return 0; 
    }

    运行2次结果如下:

    image
    image

  • 相关阅读:
    解决方案下显示的网站名称被追加编号的问题解决方法
    sql server 2008 报表服务器(sql server 2008 report service)中如何固定行或者列
    如何通过参数来切换图表和数据
    饼图中如何将一定比例的小切片收集在一起
    饼图图例中显示百分比值
    如何根据条件隐藏列
    饼图上如何显示百分比值
    负载均衡
    在UTF8页中接收和使用以GB2312方式进行URL编码的中文数据
    ASP 格式化显示时间为几个月,几天前,几小时前,几分钟前,或几秒前
  • 原文地址:https://www.cnblogs.com/staring-hxs/p/3664193.html
Copyright © 2011-2022 走看看