Slim讀 寫鎖(SRWLock)及同步方式比較

2021-07-23 13:00:54 字數 3480 閱讀 9556

一、srwlock鎖的工作原理

srwlock鎖的目的和關鍵段相同:對乙個資源進行保護,不讓其他執行緒訪問它。但是,與關鍵段不同的是:srwlock鎖允許我們區分哪些想要讀取資源的值的執行緒(讀取者執行緒)和想要更新資源的值的執行緒(寫入者執行緒)。讓所有的讀取者執行緒在同一時刻訪問共享資源應該是可行的,這是因為讀取資源並不存在破壞資源的風險。只有當寫入者執行緒想要對資源進行更新的時候才需要進行同步。在這種情況下:寫入者執行緒獨佔對資源的訪問權。

二、srwlock鎖的用法

首先,需要分配乙個srwlock結構並進行初始化:

void winapi initializesrwlock( 

_out_  psrwlock srwlock 

); 

對於srwlock結構的具體內容,我們沒有必要去詳細了解。

寫入者程序的操作

一旦srwlock的初始化完成之後,寫入者執行緒就可以呼叫acquiresrwlockexclusive,將srwlock物件的位址作為引數傳入,以嘗試獲得對被保護資源的獨佔訪問權。

void winapi acquiresrwlockexclusive( 

_inout_  psrwlock srwlock 

); 

在完成對資源的更新之後。應該呼叫releasesrwlockexclusive函式,並將srwlock物件的位址作為引數傳入,解除對資源的鎖定。

void winapi releasesrwlockexclusive( 

_inout_  psrwlock srwlock 

); 

讀取者的操作

讀取者呼叫的兩個引數是:

void acquiresrwlockshared(psrwlock srwlock);  

void releasesrwlockshared(psrwlock srwlock);  

不存在刪除或銷毀srwlock的函式,系統會自動執行清理工作。

與關鍵段相比,srwlock缺乏下面兩個特性:

(1)不存在tryenter(shared/exclusive)srwlock之類的函式。如果鎖已經被占用,那麼呼叫acquiresrwlock(shared/exclusive)會阻塞呼叫執行緒。

(2)不能遞迴呼叫srwlock。乙個執行緒不能為了多次寫入資源而多次鎖定資源,然後多次呼叫releasesrwlock來釋放對資源的鎖定。

但是,如果可以接受這些限制,就可以用srwlock來代替關鍵段,並獲得實際效能和可伸縮性的提公升。 

三、同步機制效能的比較

通過乙個簡單的基準測試可以比較各種同步機制的效能:產生1、2和4個執行緒,使用不同的同步機制重複執行相同的任務,在雙處理器上執行,得出的結果是:

使用者模式下同步機制效能的對比實驗結果如下(計數單位:微秒)

執行緒數

volatile read

volatile write

interlocked increment

critical section

srwlock shared

srwlock exclusive

mutex1

8 835 66

66 67

1060 2

8 76

153268

134148

11082 4

9145

361768

244307

23785

各種機制對比:

(1)讀取volatile長整型值,讀取非常快,因為不需要進行任何同步,與cpu的快取記憶體完全無關。

(2)寫入volatile長整型值。單執行緒的時間和讀取差不多,但是雙線程的時候時間不只是加倍,這是因為cpu之間必須相互通訊以維護快取記憶體的一致性。如果機器有更多的cpu,那麼效能還會下降,因為需要在更多的cpu之間進行通訊來使得所有cpu的快取記憶體一致。

(3)使用interlockedincrement來安全遞增乙個volatile長整型值。

它比第一種方法要慢,這是因為cpu必須鎖定記憶體。使用兩個執行緒要比乙個執行緒慢得多,這是因為必須在兩個cpu之間來回傳輸資料以維護快取記憶體的一致性。

(4)使用關鍵段來讀取乙個volatile長整型值。

關鍵段比較慢,是因為我們必須先進入再離開。進入和離開需要修改critical_section結果中的多個字段。4個執行緒需要花費更多時間,是因為上下文切換增大了發生爭奪現象的可能性。

(5)使用srwlock來讀取乙個volatile長整型值。

當有多個執行緒的時候,讀操作比寫操作快。由於多個執行緒會不斷地寫入鎖的字段以及它保護的資料,因此各cpu必須在它們的快取記憶體之間來回傳輸資料。

它的效能和關鍵段差不多,但是很多時候要優於關鍵段。建議的做法是用srwlock替代關鍵段。

(6)使用同步核心物件互斥量。

互斥量是目前效能最差的,是因為等待互斥量以及後來釋放互斥量需要執行緒每次在使用者模式和核心模式之間卻換,開銷很大。

總結:應該首先嘗試不要共享資料,然後依次使用volatile讀取、volatile寫入、interlocked函式、srwlock以及關鍵段。僅當這些都不能滿足要求的時候,再使用核心物件。

例項**:

#include

#include

#include

#include

using namespace std;

dword winapi firstthread(pvoid pvparam); 

dword winapi secondthread(pvoid pvparam); 

const long count = 10000; 

long  g_nsum = 0; 

srwlock g_srwlock; //定義srwlock結構

int main() 

dword winapi firstthread(pvoid pvparam)  } 

releasesrwlockexclusive(&g_srwlock);

return 0; 

}dword winapi secondthread(pvoid pvparam) 

{ //執行讀操作 

acquiresrwlockshared(&g_srwlock); 

cout << "thread1 get the srwlock , and do reading" << endl; 

cout << "g_num = " << g_nsum << endl; 

releasesrwlockshared(&g_srwlock);

return 0; 

多執行緒 十一 讀寫鎖SRWLock

參考自 本篇將介紹一種新方法 讀寫鎖srwlock 來解決這一問題。讀寫鎖在對資源進行保護的同時,還能區分想要讀取資源值的執行緒 讀取者執行緒 和想要更新資源的執行緒 寫入者執行緒 對於讀取者執行緒,讀寫鎖會允許他們併發的執行。當有寫入者執行緒在占有資源時,讀寫鎖會讓其它寫入者執行緒和讀取者執行緒等...

使用者模式下的執行緒同步 Slim讀 寫鎖

srwlock的目的和關鍵段一樣,但不同的是srwlock可以區分哪些執行緒要讀取共享資源,哪些要更新共享資源。讀取共享資源的執行緒因為不會破壞共享資源的資料,故這些執行緒可以同時讀取同一共享資源,但要更新共享資源的執行緒必須獨佔共享資源,此時讀取執行緒也沒有許可權訪問共享資源。更新執行緒 1.定義...

讀寫鎖及死鎖

一 讀寫鎖 有些公共資料修改的機會很少,但其讀的機會很多。並且在讀的過程中會伴隨著查詢,給這種 加鎖會降低我們的程式效率。讀寫鎖可以解決這個問題。讀寫鎖本質上是一種自旋鎖 讀者 寫者 同步與互斥 寫者 寫者 互斥 讀者 讀者 共享 沒關係 面試題 為什麼消費者與消費者之間是互斥而讀者與讀者之間是沒關...