[英]Spin Lock Implementations (OSSpinLock)
我剛剛開始研究多線程編程和線程安全性。 我熟悉忙碌等待,經過一些研究后,我現在熟悉自旋鎖背后的理論,所以我想我會看一下OSSpinLock在Mac上的實現。 它歸結為以下函數(在objc-os.h中定義):
static inline void ARRSpinLockLock(ARRSpinLock *l)
{
again:
/* ... Busy-waiting ... */
thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1);
goto again;
}
( 完全實施 )
在做了一些挖掘之后,我現在已經大致了解了thread_switch
的參數是什么( 這個站點是我發現它的地方)。 我對我所讀到的內容的解釋是,對thread_switch的這一特定調用將切換到下一個可用線程,並將當前線程的優先級降低到1個周期的絕對最小值。 '最終'(在CPU時間內)此線程將再次變為活動狀態並立即再次執行goto again;
重新開始忙碌等待的指令。
我的問題是,為什么這個電話實際上是必要的? 我發現了一個自旋鎖的另一種實現方式(適用於Windows這段時間), 在這里 ,它不包括(Windows的當量)的線程切換調用的。
您可以通過多種不同方式實現自旋鎖。 如果您找到另一個針對Windows的SpinLock
實現,您將看到另一種算法(它可能涉及SetThreadPriority
, Sleep
或SwitchToThread
)。
ARRSpinLockLock
默認實現非常聰明,在第一個旋轉周期后,它“ ARRSpinLockLock
”一段時間的線程優先級,這具有以下優點:
NOP
或PAUSE
。 Windows實現不會這樣做,因為Windows API不提供該機會(沒有等效的thread_switch()
函數,並且對SetThreadPriority
多次調用可能效率較低)。
我實際上並不認為他們是那么不同。 在第一種情況下:
static inline void ARRSpinLockLock(ARRSpinLock *l)
{
unsigned y;
again:
if (__builtin_expect(__sync_lock_test_and_set(l, 1), 0) == 0) {
return;
}
for (y = 1000; y; y--) {
#if defined(__i386__) || defined(__x86_64__)
asm("pause");
#endif
if (*l == 0) goto again;
}
thread_switch(THREAD_NULL, SWITCH_OPTION_DEPRESS, 1);
goto again;
}
我們試圖獲得鎖定。 如果失敗了,我們在for
循環中旋轉,如果它在此期間可用,我們會立即嘗試重新獲取它,如果不是,我們放棄CPU。
在另一種情況下:
inline void Enter(void)
{
int prev_s;
do
{
prev_s = TestAndSet(&m_s, 0);
if (m_s == 0 && prev_s == 1)
{
break;
}
// reluinquish current timeslice (can only
// be used when OS available and
// we do NOT want to 'spin')
// HWSleep(0);
}
while (true);
}
請注意if
下面的注釋,它實際上表示如果操作系統為我們提供該選項,我們可以旋轉或放棄CPU。 事實上,第二個例子似乎只是讓那個部分留給程序員[插入你在這里繼續代碼的首選方式],所以從某種意義上說它不像第一個那樣完整的實現。
我對整個事情的看法,我正在評論第一個片段,就是他們試圖在能夠快速獲得鎖定(1000次迭代)和不過多地占用CPU之間取得平衡(因此我們如果鎖不可用,最終會切換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.