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; }
使用原子锁的情况:
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次结果如下: