同步互斥回顧:
併發問題: 競爭條件(競態條件)
同步確保執行緒同步
訊號量是抽象資料型別
訊號量實現一般有兩種:訊號量可以用在兩個方面:
用二值訊號量實現互斥功能:
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更高階的解決方法。訊號...
作業系統訊號量
本文將針對較為簡單的生產者消費者問題,給出利用訊號量解決問題的方法。生產者 能產生並投放資源的程序 消費者 單純使用 消耗 資源的程序 問題表述 一組 生產者程序和一 組消費者程序 設每組有多個程序 通過緩衝區發生聯絡。生產者程序將生產的產品 資料 訊息等統稱為產品 送入緩衝區,消費者程序從中取出產...