2013-09-27 41 views
0

我想使用volatile值實現一個簡單的多讀/單寫鎖。ReaderWriter無鎖實現

雖然_InterlockedXXX提供了完整的柵欄障礙,如果我是正確的,也是「易失性」關鍵字,我想知道可能的缺陷和改進。我沒有獲取/釋放語義的經驗。

我的代碼:

BOOL TryAcquireShared(LONG volatile *lpnValue) 
{ 
    LONG initVal; 

    do 
    { 
    initVal = *lpnValue; 
    if (initVal == 0x80000000L) 
     return FALSE; //a writer is active 
    } 
    while (_InterlockedCompareExchange(lpnValue, initVal+1, initVal) != initVal); 
    return TRUE; 
} 

VOID ReleaseShared(LONG volatile *lpnValue) 
{ 
    LONG initVal, newVal; 

    do 
    { 
    initVal = *lpnValue; 
    newVal = (initVal & 0x80000000L) | ((initVal & 0x7FFFFFFFL) - 1); 
    } 
    while (_InterlockedCompareExchange(lpnValue, newVal, initVal) != initVal); 
    return; 
} 

BOOL TryAcquireExclusive(LONG volatile *lpnValue) 
{ 
    LONG i, initVal, newVal; 

    do 
    { 
    initVal = *lpnValue; 
    if ((initVal & 0x80000000L) != 0) 
     return FALSE; //another writer is active or waiting 
    } 
    while (_InterlockedCompareExchange(lpnValue, initVal | 0x80000000L, initVal) != initVal); 
    //wait until no readers 
    while ((*lpnValue & 0x7FFFFFFFL) != 0) 
    ::Sleep(1); 
    return TRUE; 
} 

VOID ReleaseExclusive(LONG volatile *lpnValue) 
{ 
    _InterlockedExchange(lpnValue, 0); 
    return; 
} 

另外,如果你知道,可以處理這個庫,請告訴我。

回答

0
  • TryAcquireShared應在增加之前檢查* lpnValue是否爲0x7FFFFFFFL。
  • ReleaseShared應聲明* lpnValue沒有設置0x80000000L位,而是試圖保留它。如果您釋放共享鎖,則不應存在排他鎖。
  • TryAcquireExclusive應該只在設置0x80000000L位之前檢查* lpnValue是否爲零。
  • aquire shared和aquire exclusive都應該在每次一定數量的旋轉時都有Sleep(1)呼叫。
  • 我不明白TryAcquireExclusive中的以下部分。如果你只有一個獨家鎖,你爲什麼要等待讀者?

    while((* lpnValue & 0x7FFFFFFFL)!= 0) :: Sleep(1);

+0

感謝您的意見。其概念是:當線程要求獨佔時,高位被打開,所以請求任何類型訪問的其他線程將等待。另外線程要求不包括。鎖會等待其他線程已經持有共享鎖來完成他們的工作。 關於'0x7FFFFFFFL'檢查第一點,我沒有做檢查,因爲我認爲同時不會有太多的讀者。 –