2010-10-30 69 views
2

東西我沒有得到有關的經典算法的生產者 - 消費者問題(維基百科:)多線程:經典的生產者消費者算法

semaphore mutex = 1 
semaphore fillCount = 0 
semaphore emptyCount = BUFFER_SIZE 

procedure producer() { 
    while (true) { 
     item = produceItem() 
     down(emptyCount) 
      down(mutex) 
       putItemIntoBuffer(item) 
      up(mutex) 
     up(fillCount) 
    } 
    up(fillCount) //the consumer may not finish before the producer. 
} 

procedure consumer() { 
    while (true) { 
     down(fillCount) 
      down(mutex) 
       item = removeItemFromBuffer() 
      up(mutex) 
     up(emptyCount) 
     consumeItem(item) 
    } 
} 

我注意到,生產者和消費者都鎖定「互斥」之前與緩衝區混合,然後解鎖。如果是這種情況,即任何時候只有一個線程訪問緩衝區,我真的不知道上面的算法與簡單的解決方案有什麼區別,只需要在緩衝區中放置一個守護互斥體:

 
semaphore mutex = 1 

procedure producer() { 
    while (true) { 
     item = produceItem() 
     flag = true 
     while (flag) { 
      down(mutex) 
      if (bufferNotFull()) { 
       putItemIntoBuffer(item) 
       flag = false 
      } 
      up(mutex) 
     } 
    } 
} 


procedure consumer() { 
    while (true) { 
     flag = true 
     while (flag) { 
      down(mutex) 
      if (bufferNotEmpty()) { 
       item = removeItemFromBuffer() 
       flag = false 
      } 
      up(mutex) 
     } 
     consumeItem(item) 
    } 
} 

唯一我能想到的,需要使用'fillCount'和'emptyCount'信號量是調度

也許第一個算法是爲了確保在5個消費者正在等待一個空的緩衝區的狀態下(零'fillCount'),可以確定的是,當一個新的生產者出現時,它會經過它的「down (emptyCount)「語句,並快速獲取'互斥量'。

(而在另一種解決方案中,消費者將不必要地獲得'互斥',直到新生產者獲得它並插入項目爲止)。

我對不對?我錯過了什麼嗎?

回答

3

如果緩衝區中沒有消息,那麼消費者會停下互斥鎖,檢查緩衝區,發現它是空的,掛上互斥鎖,然後循環回來並立即重複該過程。簡而言之,消費者和生產者都陷入了佔用100%CPU核心的繁忙循環中。這不僅僅是一個理論問題。您可能會發現,每次運行程序時,計算機的風扇都會開始旋轉。

+0

感謝您的快速回復。因此,當使用正確的算法時,我需要依賴up(),down()操作而不是處理CPU ......我的意思是這種算法的前提是這些操作神奇地不這樣做,不是嗎? – bloodcell 2010-10-30 12:14:59

+1

是的,算法取決於這樣一個事實,如果信號量爲零,那麼'down()'操作會使調用它的線程進入休眠狀態,直到有人在相同的信號量上調用up()。 – 2010-10-30 12:17:41

0

如果涉及多個消費者,則存在一個亟待解決的問題。在後面的例子中,消費者檢查循環中的項目。但等到他再次嘗試時,其他消費者可能會「竊取」他的物品。下次再來一次。那不好。

+0

在釋放互斥體之前將項目從緩衝區中移除,因此如果有項目,則當前使用者獲取它。在大多數情況下,哪個消費者獲得它並不重要,但消費者永遠不會看到包含東西的空緩衝區或沒有項目的非空緩衝區。互斥對此已足夠。不過,第二個程序確實進行了很多輪詢。 – cHao 2010-10-30 12:15:38

1

不僅僅是緩衝區的鎖定正在進行。

第一個程序中的fillCount信號量是在沒有剩餘消費時暫停消費者。沒有它,你會不停地查詢緩衝區,看看有沒有什麼可以得到的,這很浪費。

同樣,當緩衝區已滿時,emptyCount信號會暫停生產者。

1

生產者/消費者模式的洞概念是共享資源(緩衝區)只有在滿足某些條件時才被訪問。並且不使用不必要的CPU週期以確保它們得到滿足。

消費者:

如果沒有要消耗(=>空緩衝器)
  • 等待。

監製:

如果沒有在緩衝區
足夠的空間
  • 等待。

而且爲它的非常重要的注意:

  • 等待=旋轉等待