多線程系列之生產者和消費者問題


  生產者消費者問題是一個著名的線程同步問題,該問題描述如下:有一個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能並發執行,在兩者之間設置一個具有多個緩沖區的緩沖池,生產者將它生產的產品放入一個緩沖區中,消費者可以從緩沖區中取走產品進行消費,顯然生產者和消費者之間必須保持同步,即不允許消費者到一個空的緩沖區中取產品,也不允許生產者向一個已經放入產品的緩沖區中再次投放產品。

  首先來簡化問題,先假設生產者和消費者都只有一個,且緩沖區也只有一個。這樣情況就簡便多了。

    第一.從緩沖區取出產品和向緩沖區投放產品必須是互斥進行的。可以用互斥鎖來完成。

    第二.生產者要等待緩沖區為空,這樣才可以投放產品,消費者要等待緩沖區不為空,這樣才可以取出產品進行消費。並且由於有二個等待過程,所以要用二個事件或者信號量來控制。

在.net中,用Monitor可以同時達到以上兩者的效果。演示如下:

1 首先,聲明一個隊列:

 _queue = new Queue<T>();

2 設置緩沖區大小:

int _maxQueueCount=1024;

3 用兩個變量來記錄生產者和消費者的數量:

  int _consumersWaiting;
  int _producersWaiting;

4 生產者生產:

       lock (_locker)
            {
                _queue.Enqueue(item);
                while (_queue.Count >= _maxQueueCount && !_isDisposed)
                {
                    _producersWaiting++;
                 Monitor.Wait(_locker);
                    _producersWaiting--;
                }
                if (_consumersWaiting > 0)
                    Monitor.PulseAll(_locker);
            }

生產者在隊列的長度大於緩沖區之后,釋放鎖並進入等待狀態,同時通知消費者。

5 消費者開始消費:

 lock (_locker)
 { 
 //消費所有數據
  if (_producersWaiting > 0)
         Monitor.PulseAll(_locker);
    _consumersWaiting++;
    Monitor.Wait(_locker);
     _consumersWaiting--;
}

消費者在消費完緩沖區所有數據之后,通知生產者,釋放鎖,並進入等待狀態。

這個時候,生產者重新得到鎖,並繼續生產。

生產者與消費者變會一直有序的交叉進行下去。

 

然后再對這個簡單生產者消費者問題加大難度。將消費者改成2個,緩沖池改成擁有4個緩沖區的大緩沖池。

請讀者自行研究解決辦法。

最后,關於生產者和消費者的問題,總結如下:

1.首先要考慮生產者與消費者對緩沖區操作時的互斥。

2.不管生產者與消費者有多少個,緩沖池有多少個緩沖區。都只有二個同步過程——分別是生產者要等待有空緩沖區才能投放產品,消費者要等待有非空緩沖區才能去取產品。

 

正確掌握生產者和消費者問題的解決辦法,為開發人員的一種基本素質之一。當然Coding依然是真正掌握的不二法門:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM