典型的進程間通信IPC問題-生產者消費者問題

本實例詳細解釋了生產者消費者問題的簡易模型,對於同步互斥以及多線程處理此問題提出了一個較好的解決方案。

#include <stdio.h>
#include <pthread.h>
#define  MAX 10000000000    //定義緩衝區數量,就是生產品數量
pthread_mutex_t  the_mutex;
pthread_cond_t  condc,condp;
int buffer=0;

void *product(void *ptr)
{
    int i;
    for(i=1;i<MAX;++i)
    {
        pthread_mutex_lock(&the_mutex);//互斥使用緩衝區
        while(buffer!=0)
            pthread_cond_wait(&condp,&the_mutex);
        buffer=i;//數據放入緩衝區
        pthread_cond_signal(&condc);//喚醒消費者
        pthread_mutex_unlock(&the_mutex);//釋放緩衝區
    }
    pthread_exit;
}

void *consumer(void *ptr)
{
    int i;
    for(i=1;i<MAX;++i)
    {
        pthread_mutex_lock(&the_mutex);//互斥加鎖
        while(buffer==0)
            pthread_cond_wait(&condc,&the_mutex);
        buffer=0;
        pthread_cond_signal(&condp);//喚醒喚醒生產者
        pthread_mutex_unlock(&the_mutex);
    }
    pthread_exit(0);

}
int main(int argc,char ** argv)
{
    pthread_t  pro,con;
    pthread_mutex_init(&the_mutex,0);
    pthread_cond_init(&condp,0);
    pthread_cond_init(&condc,0);
    pthread_create(&con,0,consumer,0);
    pthread_create(&pro,0,product,0);
    pthread_join(pro,0);
    pthread_join(con,0);
    pthread_cond_destroy(&condc);
    pthread_cond_destroy(&condp);
    pthread_mutex_destroy(&the_mutex);
}

在main函數裏面包含了線程處理問題時的基本操作,包含線程創建,互斥量聲明,線程註冊的基本API函數。本實例最多可參考《Unix環境高級編程》第十二章線程控制。

  • 但是,有一點,這樣的模型有極大地可能會發生死鎖現象。死鎖造成的四個條件是
    • 形成互斥條件。每個資源要麼已經分配了一個進程,要麼就是可用的。
    • 佔有和等待條件。已經得到了某個資源的進程可以請求新的資源。
    • 不可搶佔條件,就是已經分配給一個進程的資源不能強制被搶佔,他只能被佔有他的進程顯示主動的釋放,
    • 環路等待條件,就是死鎖發生時,系統一定有一個或兩個以上的進程組成的一個環路,在循環等待資源。但是卻沒有釋放資源。
    • 死鎖發生是,四個條件肯定都滿足。如果任何一條件不成立,那麼也就不會發生死鎖。

死鎖如何避免呢?
同樣有四種方式
- 忽略該問題,如果你忽略他,那麼他也會忽略你,非著名鴕鳥算法。然而,這種想法也就是想想、
- 檢測死鎖並恢復,檢測死鎖是否發生,一旦發生,採取措施補救,亡羊補牢。
- 仔細對資源進行分配,動態避免死鎖。
- 破壞死鎖的四個必要條件,任意一個條件不滿足那麼,死鎖就不會發生。

管程是什麼?
- 一個管程是一個由過程,變量,及數據結構組成的一個集合。他們組成一個特殊的模塊和軟件包,程序可以在任意時刻調用管程中的過程,但他們不能再管程之外聲明的過程中直接使用管程中的數據結構。另外,管程是概念語言,C語言不支持管程。

monitor example
    integer i;
    condition c;
    produce producer();


    end;
    producer  consumer();
end monitor;

以下是採用java實現管程方式的生產者消費者問題,說到底,其實就是採用了一個輔助類,

public class ProducerConsumer{
    static final int N=100;
    static producer p=new producer();
    static consumer c=new consumer();
    static our_monitor mon =new our_monitor();//創建新的管程
    public static void main (String args[]){
        p.start();
        c.start();
    }
    static class producer extend Thread {
        public  void run(){
            int item;
            while(true){
                item=produce_item();
                mon.insert(item);
            }
        }
        private int produce_item(){//生產活動中。。。}
    }
    static class consumer extend Thread{
        public void run(){
            int item ;
            while(true){
                item=mon.remove();
                consumer_item(item);
            }
        }
        private void consumer_item(int item){//消費。。。。}
    }

    static class our_monitor{
        private int buffer[]=new int[N];
        private int count=0,io=0,hi=0;//計數器和索引
        public synchronized void insert (int val){
            if(count==N) 
                go_to_sleep();
            buffer[hi]=val;
            hi=(hi+1)%N;
            count++;
            if(count==1)
                notify();
        }
        public synchronized int remove(){
            int val;
            if(count==0)
                go_to_sleep();
            val=buffer[io];
            io=(io+1)%N;
            count--;
            if(count=N-1)
                notify();//如果生產者在休眠,喚醒生產者
            return val;
        }
        private void go_to_sleep(){
            try{
                wait();
            }
            catch(interruptedException exc){}
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章