操作系統2.3.11 管程

一、爲什麼要引入管程

爲了實現進程的同步,互斥操作,我們引入了信號量機制。

但信號量機制存在問題:我們編寫程序困難,容易出錯。

於是爲了方便實現進程的同步,互斥操作提出了管程。

 

二、管程的組成和基本特性

1、管程的組成

2、管程的基本特性

1)局部於管程的數據只能被局部於管程內的過程所訪問

2)一個進程只有通過調用管程內的過程才能進入管程訪問共享數據

3)每次僅允許一個進程在管程內執行某個內部過程

 

三、用管程解決生產者消費者問題

//管程
monitor ProducerConsumer
condition full,empty; //條件變量用來實現同步(排隊)
int count=0; //緩衝區中的產品數
void insert(Item item) //把產品item放入緩衝區
{
    if(count == N)
        wait(full); //緩衝區滿了,自動堵塞
    count++;
    inset_item(item);
    if(count == 1) //如果這個產品放入緩衝區後,共有一個產品,則可能有消費者進程在等待
        signal(empty) //喚醒empty隊列的隊頭消費者進程
}

Item remove()
{
    if(count == 0) //說明緩衝區中無產品
        wait(empty); //消費者進程自動堵塞,進入empty隊列等候
    count--;
    if(count == N-1) //緩衝區有空閒了
        signal(full); //喚醒full隊列中的生產者進程
}
end monitor;
//生產者進程
Producer()
{
    while(1)
    {
        item = 生產的產品;
        ProducerConsumer.insert(item);
    }
}
//消費者進程
Producer()
{
    while(1)
    {
        ProducerConsumer.remove();
        消費產品item;
    }
}

由於每次只允許一個進程在管程內執行每個內部過程,所以由編譯器負責實現各個進程互斥的進入管程的過程

總而言之,引入管程無非就是更方便地實現進程互斥和同步。

1)需要在管程中定義共享數據(如生產者消費者進程中的緩衝區)

2)需要在管程中定義用於訪問這些數據的入口——其實就是一些函數(如生產者消費者進程中,可以定義一個函數將產品放入緩衝區,在定義一個函數將產品從緩衝區取出)

3)只有通過這些特定的入口才能訪問數據

4)管程中有很多入口(函數),但是每次只能開放一個入口(函數),並且只讓一個進程進入,這樣就實現了進程的互斥。注:這種特性由編譯器實現程序員不需要關心

5)可以在管程中設置條件變量等待/喚醒操作來解決同步問題。可以讓一個進程或者線程在條件變量上等待(此時,該進程應該釋放管程的使用權,也就是讓出函數入口);可以通過喚醒操作將等待在變量上的進程或線程喚醒

 

四、Java中類似於管程的機制

在Java中,如果使用關鍵字synchronize來描述一個函數,那麼這個函數同一時間只能被一個進程調用。

如果多個線程同時調用函數,則後來者需要排隊等待。

static class monitor{
    private Iteam buffer[] = new Item[N];
    private int count=0;
    
    public synchronize void insert(Item item){
        .......
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章