它們是如何實現的,特別是在pthreads的情況下。他們在引擎蓋下使用什麼pthread
同步API?一些僞代碼將不勝感激。如何在pthread中實現讀/寫鎖?
回答
我沒有做過編程一會兒任何並行線程,但是當我這樣做,我從來沒有使用POSIX讀/寫鎖。問題是大多數時候互斥體就足夠了:即。你的關鍵部分很小,而且該地區的表現並不那麼重要,以至於雙重障礙值得擔心。
在這種情況下,性能是一個問題,通常使用原子操作(通常作爲一個編譯器擴展)是一個更好的選擇(即額外的障礙是問題,而不是臨界區的大小)。
通過你消除所有這些情況的時候,你留下,你必須需要一個真正的RW鎖定特定的性能/公平/ RW偏置要求的情況;那就是當你發現POSIX rw-lock的所有相關性能/公平參數都是未定義的和實現特定的。在這一點上,你通常會更好地實施你自己的,所以你可以確保滿足適當的公平/ rw-bias要求。
的基本算法是保持多少每個都在臨界區的計數,如果一個線程不允許訪問的是,分流其關閉,以一個合適的隊列中等待。你們的大部分努力都是在實施服務兩隊之間的適當公平性/偏見。
下面的C類並行線程般的僞代碼說明了什麼,我想說的。
struct rwlock {
mutex admin; // used to serialize access to other admin fields, NOT the critical section.
int count; // threads in critical section +ve for readers, -ve for writers.
fifoDequeue dequeue; // acts like a cond_var with fifo behaviour and both append and prepend operations.
void *data; // represents the data covered by the critical section.
}
void read(struct rwlock *rw, void (*readAction)(void *)) {
lock(rw->admin);
if (rw->count < 0) {
append(rw->dequeue, rw->admin);
}
while (rw->count < 0) {
prepend(rw->dequeue, rw->admin); // Used to avoid starvation.
}
rw->count++;
// Wake the new head of the dequeue, which may be a reader.
// If it is a writer it will put itself back on the head of the queue and wait for us to exit.
signal(rw->dequeue);
unlock(rw->admin);
readAction(rw->data);
lock(rw->admin);
rw->count--;
signal(rw->dequeue); // Wake the new head of the dequeue, which is probably a writer.
unlock(rw->admin);
}
void write(struct rwlock *rw, void *(*writeAction)(void *)) {
lock(rw->admin);
if (rw->count != 0) {
append(rw->dequeue, rw->admin);
}
while (rw->count != 0) {
prepend(rw->dequeue, rw->admin);
}
rw->count--;
// As we only allow one writer in at a time, we don't bother signaling here.
unlock(rw->admin);
// NOTE: This is the critical section, but it is not covered by the mutex!
// The critical section is rather, covered by the rw-lock itself.
rw->data = writeAction(rw->data);
lock(rw->admin);
rw->count++;
signal(rw->dequeue);
unlock(rw->admin);
}
類似上面的代碼是任何rwlock實現的起點。仔細考慮一下你的問題的本質,並用適當的邏輯代替出列,以確定下一步應該喚醒哪一類線程。根據應用情況,允許有限數量/期限的讀者跨越作家或反過來是很常見的。
當然,我的一般偏好是完全避免rw-locks;通常通過使用原子操作,互斥鎖,STM,消息傳遞和持久數據結構的某種組合。然而,有些時候你真正需要的是一個rw-lock,而當你這樣做的時候,知道它們是如何工作是很有用的,所以我希望這有助於它。
編輯 - 爲響應(很合理)的問題,我在哪裏等待上面的僞代碼:
我已經假定出隊實現包含的等待,讓內某處append(dequeue, mutex)
或prepend(dequeue, mutex)
有是一段代碼:
while(!readyToLeaveQueue()) {
wait(dequeue->cond_var, mutex);
}
這就是爲什麼我在相關互斥體中傳遞給隊列操作的原因。
你能指出一個關於爲什麼以及如何避免RW鎖的更詳細的解釋嗎?我一直在我認爲不應該的地方使用pthread RW鎖,並想更多地瞭解您所談論的內容。 – puffadder
這不是關於避免RW鎖。正如我在回答中所說的,當你需要一個RW鎖時,你應該使用一個。問題在於,很少需要RW鎖,也不需要偏見/公平性要求。 Posix RW鎖沒有任何偏見/公平保證,因此在您可能想要使用它們的時候,它們具有諷刺意味的不可移植性。鑑於實現您自己的便攜式RW鎖並不難,您也可以。 – Recurse
你在哪裏等待代碼中的信號。我在幾個地方看到了信號(rw-> deque),但是沒有代碼要等待那個信號。 – pythonic
每一個實現可以是不同的,但通常他們都贊成在默認情況下由於POSIX的要求讀者一個線程能夠獲得上rwlock中多次讀鎖。如果他們喜歡編寫者,那麼只要編寫者等待,讀者就會在第二次讀取鎖定嘗試時死鎖,除非實現可以確定讀者已經擁有讀鎖定,但唯一確定的方法是存儲所有線程的列表它們擁有讀鎖,這在時間和空間要求上效率非常低。
您的評論僅適用於重入rw-lock。正如我的回答所證明的,非重入鎖只需要一個計數。而且,列表是實施重入的數據結構的一個很差的選擇。短陣列,位圖和線性哈希表的緩存意識組合可以使簿記更有效地利用空間/時間。 – Recurse
通過折返你是否意味着遞歸?重入是比遞歸鎖定更強的要求。 –
- 1. pthread讀寫鎖定FIFO?
- 2. 讀寫在C++鎖實現
- 3. 如何實現脫機讀寫鎖
- 4. 如何在MySQL中實現「讀取然後寫入鎖定」?
- 5. Swift pthread讀/寫鎖需要一段時間才能釋放鎖
- 6. pthread讀/寫同步
- 7. 僅使用互斥鎖的讀/寫鎖實現?
- 8. MVCC實現中的無鎖讀/寫器同步
- 9. Pthread Mutex鎖定
- 10. Pthread的鎖定
- 11. 在CoreBluetooth.framework中實現讀/寫特性
- 12. 讀/寫Lock實現在Java中
- 13. 如何使用NPTL在Linux內核(> 2.6)中實現pthread?
- 14. 在Linux內核3.2中如何實現pthread?
- 15. 如何實現鎖定?
- 16. 讀寫鎖
- 17. Postgres寫/讀鎖
- 18. 讀寫鎖表
- 19. 自己的pthread鍵實現
- 20. 是否有針對ruby的'標準'讀/寫鎖定實現?
- 21. pthread mutex如何解鎖工作?線程同時出現嗎?
- 22. pthreads:讀寫器鎖,將讀鎖升級到寫鎖
- 23. PThreads:讀/寫鎖:如何檢查線程是否持有寫鎖?
- 24. Perl中的讀寫鎖
- 25. 在OpenMP和Pthread中使用鎖定
- 26. 如何在php中實現url重寫
- 27. 如何在ASP.Net中實現URL重寫?
- 28. 如何在nHibernate中實現大寫?
- 29. 無鎖讀寫器
- 30. 表鎖讀寫ALIAS
也許你可以閱讀代碼? – tbert
也許[this](http://www.cognitus。淨/ html/howto/pthreadSemiFAQ_10.html)可以提供幫助嗎? –