線程同步方法
一 windows下的方法
1 原子訪問系列函數(優點是相對於其他的方案, 執行效率高)
(1)原子加減法
LONG __cdecl InterlockedExchangeAdd(LONG volatile*Addend,LONG Value);
LONGLONG __cdecl InterlockedExchangeAdd64(LONGLONG volatile*Addend,LONGLONG Value);
分別針對32位/64位有符號整數進行原子加法的操作, 當Value為負數時, 做原子減法,返回初始值
(2) 原子替換
LONG __cdecl InterlockedExchange(LONG volatile *Target,LONG Value);//32位
SHORT __cdecl InterlockedExchange16(SHORT volatile *Target,SHORT Value);//16位
LONG LONG __cdecl InterlockedExchange64(LONG LONG volatile *Target,LONGLONG Value);//64位
PVOID __cdecl InterlockedExchangePointer(PVOID volatile *Target,PVOID Value); //這個本意是用來替換指針變量的, 其實也可以用來替換普通的變量, 此時PVOID可以理解成VOID
把第一個參數的指向的值替換為第二個參數, 並返回替換之前的值, 其中最後一個是自適應的函數, 在32位系統下替換32位值, 64位替換64位值, 返回的是替換之前的值
(3)原子比較替換
LONG __cdecl InterlockedCompareExchange(LONG volatile *Destination, LONG Exchange,LONG Comparand);
LONGLONG __cdecl InterlockedCompareExchange64(LONGLONG volatile *Destination, LONGLONG Exchange,LONGLONG Comparand);
PVOID __cdecl InterlockedCompareExchangePointer(PVOID volatile *Destination, PVOID Exchange,PVOID Comparand);
先比較再替換, 如果不同則不替換
2 使用關鍵段(優點: 內部會使用1中的函數, 運行效率比較高; 缺點: 不能跨進程使用)
(1)初始化函數
CRITICAL_SECTION cs;
void __stdcall InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
BOOL WINAPI InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
兩個的區別是第二個在使用關鍵段的同時也使用自旋鎖, 當某個要進入臨界區的線程被判定為需要等待時, 先使用自旋鎖方式進行等待, 然後再進入等待狀態.
使用場景是如果等待的時間比較短, 這種效率會更高,因為使線程進入等待狀態需要使用大約1000個cpu周期. 第二個參數一般設置為4000以下
(2)進入離開臨界區
void WINAPI EnterCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
void WINAPI LeaveCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
(3)刪除結構體
void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
線程同步方法