首先,我知道它可以用互斥量和條件變量實現,但我希望實現最有效的實現。 當沒有爭用時,我想要一個快速路徑的信號量。在Linux上,使用futex很容易;例如,這裏有一個等待:Windows上的快速計數信號量?
if (AtomicDecremenIfPositive(_counter) > 0) return; // Uncontended
AtomicAdd(&_waiters, 1);
do
{
if (syscall(SYS_futex, &_counter, FUTEX_WAIT_PRIVATE, 0, nullptr, nullptr, 0) == -1) // Sleep
{
AtomicAdd(&_waiters, -1);
throw std::runtime_error("Failed to wait for futex");
}
}
while (AtomicDecrementIfPositive(_counter) <= 0);
AtomicAdd(&_waiters, -1);
和崗位:
AtomicAdd(&_counter, 1);
if (Load(_waiters) > 0 && syscall(SYS_futex, &_counter, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0) == -1) throw std::runtime_error("Failed to wake futex"); // Wake one
起初我以爲的Windows只使用NtWaitForKeyedEvent()。問題在於它不是直接替換,因爲它在進入內核之前不會自動檢查_counter處的值,所以可能會錯過NtReleaseKeyedEvent()的喚醒。更糟的是,NtReleaseKeyedEvent()會阻塞。 什麼是最好的解決方案?
信號量限制併發訪問共享資源的數量。互斥體將訪問序列化,以便併發用戶必須等待。你要哪個? – AJG85
信號量。互斥鎖應該被鎖定它們的線程解鎖。我需要線程等待其他人發佈的信號量。 –
嗯..第一個想法:如果信號計數由一個整數表示,sema上的原子減量導致負數表示調用者需要等待。導致零或負結果的sema上的原子增量表示需要釋放一個等待線程。這是否會與你的'超級CS'之一一起保護線程等待的事件列表,在某些情況下爲更快的「無內核」路徑創建更好的信號量? –