線程同步之讀寫鎖(鎖操作的補充)
輕量級的讀寫鎖(Slim Reader-Writer locks):讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。
這種鎖相對於自旋鎖而言,能提高並發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實際的邏輯CPU數。
寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數相關),但不能同時既有讀者又有寫者。
讀寫鎖比起mutex具有更高的適用性,具有更高的並行性,可以有多個線程同時占用讀模式的讀寫鎖,但是只能有一個線程占用寫模式的讀寫鎖,讀寫鎖的三種狀態:
1.當讀寫鎖是寫加鎖狀態時,在這個鎖被解鎖之前,所有試圖對這個鎖加鎖的線程都會被阻塞
2.當讀寫鎖在讀加鎖狀態時,所有試圖以讀模式對它進行加鎖的線程都可以得到訪問權,但是以寫模式對它進行加鎖的線程將會被阻塞
3.當讀寫鎖在讀模式的鎖狀態時,如果有另外的線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨後的讀模式鎖的請求,這樣可以避免讀模式鎖長期占用,而等待的寫模式鎖請求則長期阻塞。
SRW代表-------Slim Reader-Writer
函數解析:
1.// 初始化讀寫鎖
VOID WINAPI InitializeSRWLock
(
__out PSRWLOCK SRWLock
);
函數功能:初始化讀寫鎖
2.// 獨占式訪問
VOID WINAPI AcquireSRWLockExclusive
(
__inout PSRWLOCK SRWLock
);
函數功能:寫入者線程申請寫資源。
3.// 獨占式釋放
VOID WINAPI ReleaseSRWLockExclusive
(
__inout PSRWLOCK SRWLock
);
函數功能:寫入者線程寫資源完畢,釋放對資源的占用。
4.// 共享式訪問
VOID WINAPI AcquireSRWLockShared
(
__inout PSRWLOCK SRWLock
);
函數功能:讀取者線程申請讀資源。
5.// 共享式釋放
VOID WINAPI ReleaseSRWLockShared
(
__inout PSRWLOCK SRWLock
);
函數功能:讀取者線程結束讀取資源,釋放對資源的占用。
註意點:
1.訪問方式只能選擇其一,不可以同時使用。即一個線程僅能鎖定資源一次,不能多次鎖定資源。
2.讀寫鎖聲明後要初始化,但不用銷毀,系統會自動清理讀寫鎖。
3.讀取者和寫入者分別調用不同的申請函數和釋放函數。
區別:
1.AcquireSRWLockExclusive搶占式的,當線程上鎖後,其他線程無法進行訪問。直到 ReleaseSRWLockExclusive,釋放後。一般用於寫操作。
2.AcquireSRWLockShared 是共享式的,即使線程上鎖後,其他線程也可以進行再次訪問。一般用於讀操作。
源代碼: // Semaphore.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include <Windows.h> #include <process.h> //線程數 #define g_nThreadNum 3 //信號量 SRWLOCK g_srwLock; //累加數 int g_nCount = 50; unsigned _stdcall WriteThread(void * lParam) { // 獨占式訪問 AcquireSRWLockExclusive(&g_srwLock); g_nCount++; // 獨占式釋放 ReleaseSRWLockExclusive(&g_srwLock); return 0; } unsigned _stdcall ReadThread(void *lParam) { // 共享式訪問 AcquireSRWLockShared(&g_srwLock); printf("g_nCount=%d\n", g_nCount); // 共享式釋放 ReleaseSRWLockShared(&g_srwLock); return 0; } int _tmain(int argc, _TCHAR* argv[]) { //// 初始化讀寫鎖 InitializeSRWLock(&g_srwLock); //啟動線程 HANDLE pThread[g_nThreadNum]; pThread[0] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0); pThread[1] = (HANDLE)_beginthreadex(NULL, 0, WriteThread, NULL, 0, 0); pThread[2] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0); //等待線程結束 WaitForMultipleObjects(g_nThreadNum, pThread, TRUE, INFINITE); printf("g_nCount:%d\n", g_nCount); //釋放資源 for (int i = 0; i < g_nThreadNum; ++i) { CloseHandle(pThread[i]); } getchar(); return 0; }
線程同步之讀寫鎖(鎖操作的補充)