大多數搜索結果__sync_local_test_and_set都提到它可用于實作自旋鎖而不是互斥鎖。文章多執行緒編程:鎖的效率也讀作:I could not think of a means to implement mutex without closely interacting with the kernel(futex system call)并且還給出了一個用__sync_lock_test_and_set.
但我認為__sync_lock_test_and_set也可以用來實作互斥鎖:
if (__sync_lock_test_and_test(&lock, 1) == 0) {
// we get the lock, do our work
lock = 0; // or __sync_lock_release(&lock);
} else {
// the lock has already been token.
}
這可以用作互斥鎖嗎?
提前致謝!
uj5u.com熱心網友回復:
首先,__sync_*內置函式是特定于 Linux 內核的。在其他情況下,您可能希望使用來自(或來自 的 C 11)的 C11 原子型別和<stdatomic.h>函式。std::atomic<atomic>
就目前而言,您的演算法有效。但問題是里面有什么// the lock has already been taken。你在那個街區做什么?在大多數情況下,您必須做的“作業”不是可選的。你不能跳過它;您必須等待并在鎖可用時立即執行。本質上,您撰寫的只是典型互斥鎖的trylock和unlock功能。更難的是lock。
你想要:
在不消耗 CPU 的情況下等待互斥鎖
喚醒并在互斥鎖可用時立即使用它,而不會造成不必要的延遲
如果多個執行緒正在等待互斥鎖,請在它們之間進行公平仲裁,以免沒有一個執行緒被餓死。
你可以通過做類似的事情來完成#1
while (atomic_flag_test_and_set(&lock, 1) == 1) {
thrd_yield();
// or: thrd_sleep(short_time);
}
但是你仍然會頻繁喚醒等待執行緒,只是為了測驗互斥鎖,發現它仍然不可用,然后重新進入睡眠狀態。總而言之,這可能不會消耗太多 CPU 時間,但它確實會強制進行很多不必要的背景關系切換,這不是免費的。
這在#2 上效果不是很好,因為當互斥鎖可用時,該執行緒不會立即喚醒以獲取它;它必須等到它碰巧獲得另一個時間片(在 的情況下thrd_yield())或直到它short_time到期。這會不必要地減慢您的程式。
它根本沒有完成#3。如果多個執行緒在同一個互斥體上等待,那么最終哪個執行緒占用它基本上是隨機的,并且有些執行緒最終可能會不公平地等待比其他執行緒更長的時間。
所以你真的需要作業系統的支持才能lock正常作業。作業系統可以創建一個等待這個特定互斥體的執行緒佇列,只要它不可用就讓它們處于休眠狀態。當另一個執行緒解鎖互斥鎖時,作業系統可以選擇佇列中最舊的執行緒(或應用其他一些聰明的基于優先級的演算法),喚醒那個執行緒并且只喚醒那個執行緒,并確保它在喚醒時確實持有互斥鎖。
如果沒有作業系統的支持,除了自旋鎖或它的一些稍微美化的變體之外,你什么也做不了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/517036.html
標籤:多线程并发锁定
