2011-10-15 76 views
3

如果我有多個信號量,那麼在至少有一個信號量空閒之前如何獲得進程塊?我知道我可以如用忙等待循環做到這一點:等待多個信號而無需等待(C/C++ Linux)

// blocks until one of the semaphores in sems is free, returns 
// index of semaphore that was available 
int multiple_sem_wait(sem_t **sems, int num_sems) { 
    while (true) { 
     for (int i = 0; i < num_sems; ++i) { 
     if (sem_trywait(sems[i]) == 0) { 
      return i; 
     } 
     } 
    } 
} 

但是,有沒有辦法做到這一點沒有一個繁忙的循環?也許除了應該使用的信號量外,還有一些IPC技術?

感謝

+2

而不是使用信號量,如何使用條件變量? –

回答

4

Here (developers.sun.com)是來自Sun他們如何實現他們的WaitForMultipleObjects仿真在Solaris中很短的紙張。基本的想法是將一個條件變量列表關聯到一個句柄(受互斥鎖保護),並在發送句柄時發信號通知所有條件變量。每次調用模擬的WaitForMultipleObjects時,都會創建一個新的條件變量並將其添加到您感興趣的所有句柄的列表中。在WaitForMultipleObjects仿真中,您將禁用條件變量,並在醒來時檢查每個句柄。

條件變量列表(而不是單個列表)的原因是您可能在句柄上有兩個線程阻塞:線程1在A和B上被阻塞,並且線程2在A和C上被阻塞。信號B不應該喚醒線程2.因爲每次調用WaitForMultipleObjects都會創建一個新的條件變量,在這種情況下,B和C每個都會有一個不同的條件變量,而A將同時具有兩個條件變量。

有關更詳細的信息,您需要閱讀文章本身。

+1

Sun網站已刪除鏈接的網址。 Internet Archive有一個副本:[https://web.archive.org/web/*/http://developers.sun.com/solaris/articles/waitfor_api.pdf](https://web.archive.org /web/*/http://developers.sun.com/solaris/articles/waitfor_api.pdf) –

+0

這裏提出的解決方案允許等待所有或任何(根據函數參數選擇)「solaris_win32_event_t類型的事件」 '。這是一個(有點過時的?)如何實現訂閱模型的例子,但沒有提供問題的答案。因此,這個「解決方案」需要先解決問題,然後才能使用它 - 通過在單獨的線程中等待每個信號量並從那裏發信號通知「事件」。 – Zrin

0

使用多個獨立的服務員線程,如:

  • 在一個單獨的信號的每個線程等待。
  • 在成功等待信號量後,任何給定的服務器線程信號(通過另一個信號量,條件變量或任何原語是最方便的)想要「等待多個信號量」的線程。
+0

看來這個「解決方案」要求您在使用它之前解決問題。所以現在等待的線程需要等待多個「任何最方便的原語」才能變成信號而不是多個信號量。似乎並不容易。 –

+0

不,它等待任何單獨的服務器線程發出信號的單個原語。正如線程A在sem A上等待一樣,線程B在sem B上等待,線程C在sem C上等待,但是如果成功,它們中的任何一個都會發送到主服務器正在等待的sem X上。當然,實際上你會想讓它變得更有趣,所以主要的服務員知道哪一個成功了。 –

+0

哦,我對vhallac提到的可以等待ALL的'WaitForMultipleObjects'感到困惑。等待任何事情都很簡單,只需使用'select'或'poll'即可。 –