6

我們可以使用新的條件變量原語或Windows事件來同步WinNT v6.x或更高版本中的線程。考慮以下兩種方法,我們希望工作人員在main中設置「go」時同時運行,否則應全部阻止。Windows條件變量與事件

/*language C code*/ 
/*Windows Condition Variable*/ 
int go=0; 
CONDITION_VARIABLE cv; 
SRWLOCK lock; 
void workers() 
{ 
    AcquireSRWLockShared(&lock); 
    if(go==0) 
    { 
     SleepConditionVariableSRW(&cv, &lock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED); 
    } 
    ReleaseSRWLockShared(&lock); 
    /* 
    Workers continue... 
    */ 
} 
void main() 
{ 
    int i; 
    InitializeConditionVariable(&cv); 
    InitializeSRWLock(&lock); 
    for(i=0;i<10;i++) 
    { 
     CreateThread(0, 0, workers, 0, 0, 0); 
    } 
    AcquireSRWLockExclusive(&lock); 
    go=1; 
    ReleaseSRWLockExclusive(&lock); 
    WakeAllConditionVariable(&cv); 
} 

/*language C code*/ 
/*Windows Event*/ 
HANDLE go; 
void workers() 
{ 
    WaitForSingleObject(go, INFINITE); 
    /* 
    Workers continue... 
    */ 
} 
void main() 
{ 
    int i; 
    go=CreateEvent(0,1,0,0); /*No security descriptor, Manual Reset, initially 0, no name*/ 
    for(i=0;i<10;i++) 
    { 
     CreateThread(0, 0, workers, 0, 0, 0); 
    } 
    SetEvent(go); 
} 

在第一方法中,工人被阻塞上SleepConditionVariableSRW和由WakeAllConditionVariable醒來。在第二個,他們被阻止在WaitForSingleObject和醒了SetEvent

哪一個在實踐中更好,只關於開銷? (提示:上下文切換鎖爭開銷阻塞線程)的

我會選擇第一個,但感覺缺乏理由的。

回答

5

這個特殊的用例非常適用於一個事件:它是一個一次性過程,所有等待的線程都必須被喚醒。

條件變量更適合於像隊列這樣的事情,在等待線程被喚醒時,有一個關聯的謂詞可能或不可能是真的(例如隊列中的項目---它們可能已被另一個線程),或者重要的是線程喚醒的是那些已經等待條件變量通知的人,而不是之後出現的線程。

正如Hans指出的那樣,Windows本機條件變量僅適用於Vista或更高版本,因此如果與Windows XP兼容性受到關注,則無法使用它們。

2

支持條件變量需要Vista或更高版本。通常情況下,降壓停止的地方,支持XP不幸的是仍然很重要。你的第二個片段也有很大的優勢,它是微不足道的理解。我不知道你在第一個嘗試做什麼,它看起來是錯誤的。