讀寫鎖
此條目需要精通或熟悉相關主題的編者參與及協助編輯。 (2017年11月22日) |
讀寫鎖是計算機程序的並發控制的一種同步機制,也稱「共享-互斥鎖」、多讀者-單寫者鎖。[1]多讀者鎖,[2],「push lock」[3]) 用於解決讀寫問題。讀操作可並發重入,寫操作是互斥的。這意味着多個線程可以同時讀數據,但寫數據時需要獲得一個獨占的鎖。當寫者寫數據時,其它寫者或讀者需要等待,直到這個寫者完成寫操作。讀寫鎖常見的用法是控制線程對內存中的某種數據結構的訪問,這種數據結構不能被原子性地更新,並且在完成更新之前都是無效的。
某些讀寫鎖允許在讀模式與寫模式之間升降級。[1]
優先級策略
讀寫鎖可以有不同的操作模式優先級:
- 讀操作優先鎖:提供了最大並發性,但在鎖競爭比較激烈的情況下,可能會導致寫操作飢餓。這是由於只要還有一個讀線程持鎖,寫線程就拿不到鎖。多個讀者可以立刻拿到鎖,這意味着一個寫者可能一直在等鎖,期間新的讀者一直可以拿到鎖。極端情況下,寫者線程可能會一直等鎖,直到所有一開始就拿到鎖的讀者釋放鎖。讀者的可以是弱優先級的,如前文所述,也可以是強優先級的,即只要寫者釋放鎖,任何等待的讀者總能先拿到。
- 寫操作優先鎖:如果隊列中有寫者在等鎖,則阻止任何新讀者拿鎖,來避免了寫操作飢餓的問題。一旦所有已經開始的讀操作完成,等待的寫操作立即獲得鎖。[4]和讀操作優先鎖相比,寫操作優先鎖的不足在於在寫者存在的情況下並發度低。內部實現需要兩把互斥鎖。[5]
- 未指定優先級鎖:不提供任何讀/寫的優先級保證。
實現
使用兩把互斥鎖
Michel Raynal使用兩把互斥鎖與一個整數計數器實現。計數器b跟蹤被阻塞的讀線程。互斥鎖r保護b,供讀者使用。互斥鎖g (指"global")確保寫操作互斥。偽代碼:
Begin Read
- Lock r.
- Increment b.
- If b = 1, lock g.
- Unlock r.
End Read
- Lock r.
- Decrement b.
- If b = 0, unlock g.
- Unlock r.
Begin Write
- Lock g.
End Write
- Unlock g.
實現是讀操作優先。[6]:76
使用條件變量與互斥鎖
可使用條件變量c與普通的互斥鎖m、整型計數器r(表示正在讀的個數)與布爾標誌w(表示正在寫)來實現讀寫鎖。
- Lock m (blocking).
- While w:
- wait c, m[a]
- Increment r.
- Unlock m.
- Lock m (blocking).
- While (w or r > 0):
- wait c, m
- Set w to true.
- Unlock m.
lock-for-read與lock-for-write各自有自己的逆操作。unlock-for-read通過減量r並在r變為0時通知c。unlock-for-write設置w為false並通知c。[7][8][9]
程序語言支持
- POSIX標準的
pthread_rwlock_t
與相關操作[10] - ReadWriteLock[11] 接口,ReentrantReadWriteLock[5]鎖,從Java版本5開始
- Microsoft
System.Threading.ReaderWriterLockSlim
鎖,用於C#與.NET語言程序[12] std::shared_mutex
read/write鎖在C++17[13]boost::shared_mutex
與boost::upgrade_mutex
鎖在Boost C++ Libraries[14]sync.RWMutex
在Go語言[15]- Phase fair reader–writer lock[16]
std::sync::RwLock
,在Rust語言[17]- Poco::RWLock,在POCO C++ Libraries
mse::recursive_shared_timed_mutex
在SaferCPlusPlus庫,是支持std::recursive_mutex
(頁面存檔備份,存於網際網路檔案館)的recursive ownership語義的std::shared_timed_mutex
(頁面存檔備份,存於網際網路檔案館)的一個實現txrwlock.ReadersWriterDeferredLock
,用於Twisted[18]
Windows操作系統
SRWLock
,見Windows操作系統API,從Windows Vista開始.[19]
讀寫鎖(Slim reader/writer,SRW, lock)用於進程內的線程間同步。 SRW既不是公平的也不是先進先出的。讀寫鎖數據結構的內部實現就是一個指針。讀寫鎖的性能較臨界區有很大的提升,這是因為讀寫鎖是基於原子操作,關鍵段是基於event內核對象的,從用戶模式到內核模式的切換占用了大量的時鐘周期。相關API:[20]
- InitializeSRWLock:動態初始化SRW結構。也可以直接賦值SRWLOCK_INIT常量來靜態初始化SRW結構。不需要顯式析構。
- AcquireSRWLockShared:獲取共享讀的SRW鎖。
- AcquireSRWLockExclusive:獲取專享寫的SRW鎖。
- TryAcquireSRWLockShared:試圖獲取共享讀的SRW鎖。
- TryAcquireSRWLockExclusive:試圖獲取專享寫的SRW鎖。
- ReleaseSRWLockShared:釋放已經獲取的共享讀的SRW鎖。
- ReleaseSRWLockExclusive:釋放已經獲取的專享寫的SRW鎖。
- SleepConditionVariableSRW:在已經獲取SRW鎖的前提下,原子操作:在指定條件變量上睡眠並釋放SRW鎖
可選
read-copy-update (RCU)算法是讀寫鎖的一種替代實現。RCU對讀操作是無等待。Linux內核實現了很少寫操作的一種RCU叫做seqlock。
參見
注釋
- ^ This is the standard "wait" operation on condition variables, which, among other actions, releases the mutex m.
參考文獻
- ^ Hamilton, Doug. Suggestions for multiple-reader/single-writer lock?. Newsgroup: comp.os.ms-windows.nt.misc. 21 April 1995 [8 October 2010]. Usenet: [email protected]. (原始內容存檔於2012-11-09).
- ^ "Practical lock-freedom" (頁面存檔備份,存於網際網路檔案館) by Keir Fraser 2004
- ^ Push Locks – What are they?. Ntdebugging Blog. MSDN Blogs. 2009-09-02 [11 May 2017]. (原始內容存檔於2017-10-07).
- ^ Stevens, W. Richard; Rago, Stephen A. Advanced Programming in the UNIX Environment. Addison-Wesley. 2013: 409.
- ^ 5.0 5.1
java.util.concurrent.locks.ReentrantReadWriteLock
Java readers–writer lock implementation offers a "fair" mode - ^ Raynal, Michel. Concurrent Programming: Algorithms, Principles, and Foundations. Springer. 2012.
- ^ 7.0 7.1 7.2 Herlihy, Maurice; Shavit, Nir. The Art of Multiprocessor Programming. Elsevier. 2012: 184–185.
- ^ 8.0 8.1 8.2 Nichols, Bradford; Buttlar, Dick; Farrell, Jacqueline. PThreads Programming: A POSIX Standard for Better Multiprocessing. O'Reilly. 1996: 84–89.
- ^ 9.0 9.1 9.2 Butenhof, David R. Programming with POSIX Threads. Addison-Wesley. 1997: 253–266.
- ^ The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition: pthread_rwlock_destroy. The IEEE and The Open Group. [14 May 2011]. (原始內容存檔於2010-12-09).
- ^
java.util.concurrent.locks.ReadWriteLock
- ^ ReaderWriteLockSlim Class (System.Threading). Microsoft Corporation. [14 May 2011]. (原始內容存檔於2017-07-16).
- ^ New adopted paper: N3659, Shared Locking in C++—Howard Hinnant, Detlef Vollmann, Hans Boehm. Standard C++ Foundation. [2017-11-22]. (原始內容存檔於2016-08-26).
- ^ Anthony Williams. Synchronization – Boost 1.52.0. [31 Jan 2012].
- ^ The Go Programming language - Package sync. [30 May 2015]. (原始內容存檔於2018-01-03).
- ^ Reader–Writer Synchronization for Shared-Memory Multiprocessor Real-Time Systems (PDF). [2017-11-22]. (原始內容 (PDF)存檔於2017-08-10).
- ^ std::sync::RwLock - Rust. [10 December 2015]. (原始內容存檔於2019-07-17).
- ^ Readers/Writer Lock for Twisted. [28 September 2016].
- ^ Alessandrini, Victor. Shared Memory Application Programming: Concepts and Strategies in Multicore Application Programming. Morgan Kaufmann. 2015.
- ^ MSDN: Slim Reader/Writer (SRW) Locks. [2017-11-23]. (原始內容存檔於2015-04-16).