一谆级、線程需要相互通信的場景:
? 1.需要讓多個線程同時訪問一個共享資源夺英,同時不能破壞資源的完整性
? 2.一個線程需要通知其他線程某項任務已經(jīng)完成
二棚壁、同步機制性能比較
? ? ? ? 后續(xù)添加
三齿尽、原子訪問:Interlocked系列函數(shù)
? 1.以原子方式進行遞增(或遞減)
? ? ? LONG InterlockedExchangedAdd( ? ? ? ? ? ? PLONG volatile plAddend,? ? //volatile:告訴編譯器該變量可能被應用程序以外的其他東西修改亮元;不要對這個變量進行任何形式的優(yōu)化 ? ? ? ? ? ? LONG llIncrement);? ? ? ? ? ? //增量(若遞減唠摹,傳遞負值)
? ? ? ? ? ? LONGLONG InterlockedExchangedAdd64( ? ? ? ? ? PLONGLONG volatile plAddend爆捞, ? ? ? ? ? ? LONGLONG llIncrement); ? ? ? ? //若想用原子方式給一個值加一(或減一)
? ? LONG InterlockedIncrement(PLONG plAddend)? ? //++勾拉,參數(shù)為地址 ? ? ? ? LONG InterlockedDecrement(PLONG plAddend)? ? //--
? 2.以原子方式交換兩個參數(shù)指定的值(可以是變量或指針)煮甥,在實現(xiàn)旋轉(zhuǎn)鎖時常用
? ? ? LONG InterlockedExchanged( ? ? ? ? ? ? PLONG volatile plTarget, ? ? ? ? ? ? LONG lValue)藕赞;
? ? ? ? ? ? ? LONGLONG InterlockedExchanged64( ? ? ? ? ? ? PLONGLONG volatile plTarget成肘, ? ? ? ? ? ? LONGLONG lValue);
? ? ? ? ? ? ? PVOID InterlockedExchangedPointer( ? ? ? ? ? ? PVOID* volatile ppvTarget斧蜕, ? ? ? ? ? ? PVOID pvValue)双霍; ? ? ? ? //比較后旋轉(zhuǎn)(如果destination的值和比較參數(shù)相等,交換)
? ? ? ? ? ? ? PLONG InterlockedCompareExchanged(? ? ? ? ? ? //對32位系統(tǒng) ? ? ? ? ? ? PLONG plDestination批销, ? ? ? ? ? ? LONG lExchange, ? ? ? ? ? ? LONG lComparand)洒闸;
? ? ? PLONGLONG InterlockedCompareExchanged( ? ? ? ? ? ? PLONGLONG pllDestination, ? ? ? ? ? ? LONGLONG llExchange, ? ? ? ? ? ? LONGLONG llComparand)均芽;//對32位系統(tǒng)
? ? ? PVOID InterlockedCompareExchangedPointer( ? ? ? ? ? ? PVOID* ppvDestination丘逸, ? ? ? ? ? ? PVOID pvExchange, ? ? ? ? ? ? PVOID pvComparand)掀宋; //對64位系統(tǒng)
? ? 四深纲、高速緩存行
五、關鍵段
? 代碼劲妙。湃鹊。。
? ? CRITICAL_SECTION g_cs;
? ? ? ? EnterCriticalSectionThread(&g_cs);
? ? ? ? 操作部分代碼镣奋。涛舍。。
? ? LeaveCriticalSectionThread(&g_cs);
? ? 其他操作代碼唆途。富雅。掸驱。
? ? ? VOID InitializeCriticalSection(PCRITICAL_SECTION pcs); //初始化
? ? ? VOID DeleteCriticalSection(PCRITICAL_SECTION pcs);//清理
? ? ? ? ? VOID EnterCriticalSection(PCRITICAL_SECTION pcs);//進入關鍵段
? ? ? ? ? BOOL TryEnterCriticalSection(PCRITICAL_SECTION pcs);? ? //從來不會讓調(diào)用線程進入等待狀態(tài),如果資源被其他線程訪問没佑,返回FALSE毕贼;否則返回TRUE,表明線程正在訪問資源蛤奢,返回TRUE的函數(shù)必須調(diào)用對應的LeaveCriticalSection鬼癣。
? ? ? ? ? VOID LeaveCriticalSection(PCRITICAL_SECTION pcs); //離開關鍵段
? ? ? BOOL InitializeCriticalSectionAndSpinCount( ? ? ? ? ? ? PCRITICAL_SECTION pcs, ? ? ? ? ? ? DWORD dwSpinCount)啤贩;//在使用關鍵段的時候同時使用旋轉(zhuǎn)鎖待秃,初始化關鍵段
? ? ? ? ? DWORD InitialCriticalSectionCount( ? ? ? ? PCRITICAL_SECTION pcs, ? ? ? ? DWORD dwSpinCount)痹屹;//改變關鍵段的旋轉(zhuǎn)次數(shù)
? ? InitializeCriticalSection和InitializeCriticalSectionAndSpinCount比較:
? ? InitializeCriticalSectionAndSpinCount函數(shù)會先嘗試用旋轉(zhuǎn)鎖來獲得對資源的訪問權章郁。dwSpinCount是循環(huán)的次數(shù),在單處理機上志衍,會忽略dwSpinCount(其值為0)暖庄。用來保護進程堆的關鍵段所使用的循環(huán)次數(shù)大約為4000。
? ? ? ? 六楼肪、Slim 讀/寫鎖
? ? ? ? 這個方法讓多個讀取者線程在同一時刻訪問共享資源是可行的培廓,但是寫入者線程是獨占對資源的訪問權。
? ? VOID InitializeSRWLock(PSRWLOCK SRWLock);//初始化SRWLock結(jié)構(gòu)
? //不存在銷毀SRWLOCK的函數(shù)春叫,系統(tǒng)自動對其進行清理
? //寫入者
? ? VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock)肩钠; //嘗試獲得對被保護的資源的獨占訪問權
? ? ? ? VOID ReleaseSRWLockExcRellusive(PSRWLOCK SRWLock);//資源更新等操作完成后暂殖,解除對資源的鎖定
? ? //讀取者
? ? VOID AcquireSRWLockShared(PSRWLOCK SRWLock)蔬将;//獲得訪問權(非獨占)?
? VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);//解除訪問
Slim讀寫鎖和關鍵段對比:
? ? 1.不存在類似TryEnterCriticalSection的函數(shù)央星,這就導致了霞怀,如果鎖已經(jīng)被占用,那么調(diào)用AcquireSRWLockExclusive或AcquireSRWLockShared會阻塞調(diào)用線程莉给。
? ? 2.不能遞歸地獲得SRWLOCK毙石。也就是說,一個線程不能為了多次寫入資源而多次鎖定資源颓遏,然后再多次調(diào)用ReleaseSRWLockExcRellusive或ReleaseSRWLockShared來釋放對資源的綁定
? 七徐矩、條件變量(常用于生產(chǎn)者消費者問題)
? ? ? ? 如果讀取者線程沒有數(shù)據(jù)可讀,那么它應該將鎖釋放并等待叁幢,直到寫入者線程產(chǎn)生了新的數(shù)據(jù)為止滤灯; ? ? 如果接受寫入者線程產(chǎn)生的數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)已滿,那么寫入者線程應該釋放鎖并進入睡眠狀態(tài),知道讀取者線程把數(shù)據(jù)結(jié)構(gòu)清空為止鳞骤。
? //讓線程以原子方式把鎖釋放并將自己阻塞窒百,直到某個條件成立為止 ? ? BOOL SleepConditionVariableCS(? ? ? ? //關鍵段 ? ? ? ? PCONDITION_VARIABLE pConditionVariable,? ? //已初始化的條件變量豫尽。調(diào)用線程等待該條件變量 ? ? ? ? PCRITICAL_SECTION pCriticalSection篙梢, ? ? ? ? DWORD dwMilliseconds);
? BOOL SleepConditionVariableSRW( ? ? ? ? PCONDITION_VARIABLE pConditionVariable美旧,? ? ? ? ? ? PSRWLOCK pSRWLock渤滞, ? ? ? ? DWORD dwMilliseconds, ? ? ? ? ULONG Flags)榴嗅;? ? ? ? ? ? ? ? ? ? ? ? //Flags用來指定一旦條件變量被觸發(fā)妄呕,希望線程以什么方式來得到鎖。寫入者為0嗽测,表示獨占資源訪問绪励;讀取者為CONDITION_VARIABLE_LOCKMODE_SHARED,表示希望返回共享資源的訪問论咏。 ? ? //喚醒 ? ? VOID WakeConditionVariable( ? ? ? ? PCONDITION_VARIABLE ConditionVariable); ? ? VOID WakeAllConditionVariable( ? ? ? ? PCONDITION_VARIABLE ConditionVariable)颁井;
八厅贪、內(nèi)核對象
? ? 1.等待函數(shù):
WaitForSingleObject(HANDLE hObject,DWORD dwMilliseseconds)雅宾;
? ? ? ? ? ? WaitForMultipleObjects(DWORD dwCount养涮,CONST HANDLE* phObjects,BOOL bWaitAll眉抬,DWORD dwMilliseconds)贯吓;
dwMilliseconds常傳INFINITE,但要注意死鎖蜀变。
? ? 2.事件
? ? ? ? 創(chuàng)建:CreateEvent和CreateEventEx
觸發(fā):SetEvent
? ? ? ? 未觸發(fā):ResetEvent
? ? 3.可等待的計時器
? ? ? 創(chuàng)建:CreateWaitableTimer
? ? ? 得到已存在的可等待計時器句柄:OpenWaitableTimer
? ? ? 觸發(fā):SetWaitableTimer
4.信號量
? ? ? ? ? ? 創(chuàng)建:CreateSemaphore和CreateSemaphoreEx
? ? ? ? ? ? 觸發(fā):當前資源計數(shù)大于0
? ? 得到句柄:OpenSemaphore
5.互斥量內(nèi)核對象
? ? 線程ID為0(無效線程ID)悄谐,那么該互斥量不為任何線程所占用,它處于觸發(fā)狀態(tài)
? ? 如果ID非0库北,那么有一個線程已經(jīng)占用了互斥量爬舰,它處于未觸發(fā)狀態(tài)
? ? 創(chuàng)建:CreateMutex和CreateMutexEx
? ? 另一個進程得到句柄:OpenMutex