作業系統訊號量和管程

2021-10-22 20:22:12 字數 4249 閱讀 8234

同步互斥回顧:

併發問題: 競爭條件(競態條件)

同步確保執行緒同步

訊號量是抽象資料型別

訊號量實現一般有兩種:

訊號量可以用在兩個方面:

用二值訊號量實現互斥功能:

mutex = new semaphore(1);          //初始化乙個值為1的訊號量作為乙個鎖

mutex->p(); //訊號量減1

//執行臨界區**, 此時如果有其他執行緒要進入臨界區, 也需要mutex->p(), 也就會讓訊號量的值為-1,

//也就會被阻塞

mutex->v(); //訊號量加1

用二值訊號量實現同步:

condition = new semaphore(0);

// thread a

condition->p() //a執行緒等待condition->v()

// thread b

condition->v() //b執行緒喚醒, 也就是同步

用計數訊號量還可以實現生產者 - 消費者問題:

有界緩衝區(buffer)的生產者 - 消費者問題, 有以下性質:

這個問題用互斥(鎖機制)是不夠的.

而且具有正確性要求:

根據以上要求和性質:

如果每個約束用乙個單獨的訊號量, 有以下訊號量設計:

**設計:

class boundedbuffer

boundedbuffer::deposit(c)

boundedbuffer::remove(c)

針對訊號量的p()和v()操作的實現, 需要使用硬體原語:

具體實現:

class semaphore

semaphore::p()

}semaphore::v()

}

實現中需要注意的細節:

管程的目的:

分離互斥和條件同步的關注

什麼是管程:

一般方法:

簡單步驟:

獲取進入管程的鎖從而進入管程

管程中對共享資源進行操作

當需要等待時候, 訊號量呼叫wait自身睡眠並把進入管程的鎖進行釋放

當資源得到滿足, 訊號量會呼叫signal從而喚醒正在這個訊號量睡眠的執行緒

條件變數的實現:

class condition

condition::waiting(lock)

condition::signal()

}

管程實現生產者 - 消費者問題:

class boundedbuffer

boundedbffer::deposit(c)

boundedbuffer::remove(c)

問題動機:

共享資料的訪問

兩種型別的使用者:

問題的約束:

設計思路:

基於讀者優先策略的方法: 只要有乙個讀者處於活動狀態, 後來的讀者都會被接納. 如果讀者源源不斷出現的話, 那麼寫者就始終處於阻塞狀態.

sem_wait(writemutex);        //相當於writemutex->p(), 保證只有乙個執行緒在執行寫操作, 以及在寫操作過程中沒有讀操作

write;

sem_post(writemutex); //相當於writemutex->v()

sem_wait(countmutex);            //保證對rcount操作的互斥性

if(rcount == 0)

sem_wait(writemutex); //說明此時沒有讀操作, 是有可能有寫操作的, 所以需要等待寫操作結束

++ rcount;

sem_post(countmutex);

read;

sem_wait(countmutex);

-- rcount;

if (rcount == 0)

sem_post(writemutex);

sem_post(countmutex);

基於寫者優先策略的方法: 一旦寫者就緒, 那麼寫者會盡可能快地執行寫操作. 如果寫者源源不斷地出現的話, 那麼讀者就始終處於阻塞狀態.

需要的變數:

讀操作:

read()

startread()

ar ++;

lock.release();

}doneread()

lock.release();

}

寫操作:

write() 

startwrite()

lock.release();

}donewrite() else if (wr > 0)

lock.acquire();

}

問題描述(2023年由di jkstra首先踢出並解決):

5個哲學家圍繞一張圓桌而坐, 桌子上放著5支叉子, 每兩個哲學家之間放一支; 哲學家的動作包括思考和進餐, 進餐時需要同時拿起他左邊和右邊的兩支叉子, 思考時則同時將兩支叉子放回原處. 如何保證哲學家們的動作有序進行? 如: 不會出現有人永遠拿不到叉子.

共享資料:

思路:

#define n           5                //哲學家個數

#define left i //第i個哲學家的左鄰居

#define right (i + 1) % n //第i個哲學家的右鄰居

#define thinking 0 //思考狀態

#define hungry 1 //飢餓狀態

#define eating 2 //進餐狀態

int state[n]; //記錄每個人的狀態

semaphore mutex;                     //互斥訊號量, 初值1
semaphore s;                      //同步訊號量, 初值0
void philosopher(int i)

}

void take_forks(int i)

void test_take_left_right_forks(int i)

}

//功能: 把兩把叉子放回原處, 並在需要的時候,

//去喚醒左鄰右舍

void put_forks(int i)

訊號量和管程

在os引入多執行緒後,程式的多工併發功能得到了良好的支援,但同時也帶來了問題,那就是多執行緒併發會導致一些共享的資源產生競爭問題 例如對共享資料區的資料進行操作 而在計算機中,操作這種共享資源的 塊被稱為臨界區。為了解決這種競爭衝突,我們必須理解兩個概念 同步和互斥。互斥 所謂互斥,就是說,任何時候...

作業系統筆記 第10章 訊號量 管程

作業系統存在併發問題 競態條件,即多程式併發存在大的問題 作業系統同步指多執行緒共享公共資源的協調執行,包括互斥和條件同步。互斥指同一時間只有乙個執行緒可以在臨界區執行。實際條件中,確保同步正確很難。需要高層次的程式設計抽象 如 鎖 和底層硬體支援編譯。訊號量和管程是比lock更高階的解決方法。訊號...

作業系統訊號量

本文將針對較為簡單的生產者消費者問題,給出利用訊號量解決問題的方法。生產者 能產生並投放資源的程序 消費者 單純使用 消耗 資源的程序 問題表述 一組 生產者程序和一 組消費者程序 設每組有多個程序 通過緩衝區發生聯絡。生產者程序將生產的產品 資料 訊息等統稱為產品 送入緩衝區,消費者程序從中取出產...