操作系統(tǒng)知識(shí)點(diǎn)(七)——信號(hào)量

信號(hào)量

背景

信號(hào)量(semaphore)

  • 抽象數(shù)據(jù)類(lèi)型

    • 一個(gè)整形(sem),兩個(gè)原子操作

    • P():sem減1,如果sem<0,等待,否則繼續(xù)

    • V():sem加1,如果sem<=0,喚醒一個(gè)等待的P

信號(hào)量使用

特性
  • 信號(hào)量是被保護(hù)的整數(shù)變量

    • 初始化完成后,只能通過(guò)P()和V()操作修改

    • 由操作系統(tǒng)保證,PV操作是原子操作

  • P()可能阻塞,V()不會(huì)阻塞

  • 通常假定信號(hào)量是”公平的“

    • 線(xiàn)程不會(huì)被無(wú)限期阻塞在P()操作

    • 假定信號(hào)量等待按先進(jìn)先出排隊(duì)

分類(lèi)
  • 二進(jìn)制信號(hào)量:可以是0或1

  • 一般/計(jì)數(shù)(資源)信號(hào)量:可取任何非負(fù)值

  • 兩者等價(jià):基于一個(gè)可以實(shí)現(xiàn)另一個(gè)

使用
  • 互斥訪(fǎng)問(wèn):臨界區(qū)的互斥訪(fǎng)問(wèn)控制

  • 條件同步:線(xiàn)程間的事件等待

生產(chǎn)者-消費(fèi)者問(wèn)題
  • 生成者->緩沖區(qū)->消費(fèi)者

  • 有界緩沖區(qū)的生產(chǎn)者-消費(fèi)者問(wèn)題描述

    • 一個(gè)或多個(gè)生產(chǎn)者在生成數(shù)據(jù)后放在一個(gè)緩沖區(qū)里

    • 單個(gè)消費(fèi)者從緩沖區(qū)取出數(shù)據(jù)處理

    • 任何時(shí)刻只能有一個(gè)生產(chǎn)者或消費(fèi)者可訪(fǎng)問(wèn)緩沖區(qū)

  • 問(wèn)題分析

    • 任何時(shí)刻只能有一個(gè)線(xiàn)程操作緩沖區(qū)(互斥訪(fǎng)問(wèn))

    • 緩沖區(qū)空時(shí),消費(fèi)者必須等待生產(chǎn)者(條件同步)

    • 緩沖區(qū)滿(mǎn)時(shí),生產(chǎn)者必須等待消費(fèi)者(條件同步)

  • 用信號(hào)量描述每個(gè)約束

    • 二進(jìn)制信號(hào)量mutex

    • 資源信號(hào)量fullBuffers

    • 資源信號(hào)量emptyBuffers

class BoundedBuffer{
    mutex =new Semaphore(1);
    fullBuffers =new Semaphore(0);
    emptyBuffers =new Semaphore(n);
}
BoundedBuffer::Producter(c){
    emptyBuffers ->P();
    mutex ->P();
    ADD C TO THE BUFFER;
    mutex ->V();
    fullBuffers ->V();
}
BoundedBuffer::Consumer(c){
    fullBuffers ->P();
    mutex ->P();
    REMOVE C FROM BUFFER;
    mutex ->V();
    emptyBuffers ->V();
}

信號(hào)量實(shí)現(xiàn)

  • 實(shí)現(xiàn)
class Semaphore{
    int sem;
    WaitQueue q;
}
Semaphore: P(){
    sem--;
    if(sem<0){
        ADD THIS THREAD t TO q;
        block(q);
    }
}
Semaphore: V(){
    sem++;
    if(sem<=0){
        REMOVE a THREAD t FROM q;
        wakeup(t);
    }
}
  • 困難

    • 讀/開(kāi)發(fā)代碼比較困難

    • 容易出錯(cuò)。使用的信號(hào)量已經(jīng)被另一個(gè)線(xiàn)程占用;忘記釋放信號(hào)量

    • 不能夠處理死鎖問(wèn)題

管程(Moniter)

  • 管程是一種用于多線(xiàn)程互斥訪(fǎng)問(wèn)共享資源的程序結(jié)構(gòu)

    • 采用面向?qū)ο蠓椒?,?jiǎn)化了線(xiàn)程間的同步控制

    • 任一時(shí)刻最多只有一個(gè)線(xiàn)程執(zhí)行管程代碼

    • 正在管程中的線(xiàn)程可臨時(shí)放棄管程的互斥訪(fǎng)問(wèn),等待事件出現(xiàn)時(shí)恢復(fù)

  • 使用

    • 在對(duì)象/模塊中,收集相關(guān)共享數(shù)據(jù)

    • 定義訪(fǎng)問(wèn)共享數(shù)據(jù)的方法

  • 組成

    • 一個(gè)鎖:控制管程代碼的互斥訪(fǎng)問(wèn)

    • 0或者多個(gè)條件變量:管理共享數(shù)據(jù)的并發(fā)訪(fǎng)問(wèn)

  • 條件變量

    • 條件變量是管程內(nèi)的等待機(jī)制

      • 進(jìn)入管程的線(xiàn)程因資源被搶占而進(jìn)入等待狀態(tài)

      • 每個(gè)條件變量表示一種等待原因,對(duì)應(yīng)一個(gè)等待隊(duì)列

    • wait()操作

      • 將自己阻塞在等待隊(duì)列中

      • 喚醒一個(gè)等待者或釋放管程的互斥訪(fǎng)問(wèn)

    • signal()操作

      • 將等待隊(duì)列中的一個(gè)線(xiàn)程喚醒

      • 如果等待隊(duì)列為空,則等同空操作

  • 條件變量實(shí)現(xiàn)

class Condition{
    int numWaiting =0;
    WaitQueue q;
}
Condition::Wait(lock){
    numWaiting++;
    ADD this thread t to q;
    release(lock);
    schedule();
    require(lock);
}
Condition::Signal(){
    if(numWaiting >0){
        REMOVE a thread t from q;
        wakeup(t);
        numWaiting--;
    }
}
  • 管程解決生產(chǎn)者-消費(fèi)者問(wèn)題
class BoundedBuffer {
    …
    Lock lock;
    int count = 0;
    Condition notFull, notEmpty;
}
BoundedBuffer::Producter(c) {
    lock->Acquire();
    while (count == n)
        notFull.Wait(&lock);
    Add c to the buffer;
    count++;
    notEmpty.Signal();
    lock->Release();
}
BoundedBuffer::Consumer(c) {
    lock->Acquire();
    while (count == 0)    
      notEmpty.Wait(&lock);
    Remove c from buffer;
    count--;
    notFull.Signal();
    lock->Release();
}

經(jīng)典同步問(wèn)題

讀者-寫(xiě)者問(wèn)題
  • 共享數(shù)據(jù)的兩類(lèi)使用者

    • 讀者:只讀取數(shù)據(jù),不修改

    • 寫(xiě)者:讀取和修改數(shù)據(jù)

  • 讀者-寫(xiě)者問(wèn)題描述:對(duì)共享數(shù)據(jù)的讀寫(xiě)

    • 讀-讀允許:同一時(shí)刻允許有多個(gè)讀者同時(shí)讀

    • 讀-寫(xiě)互斥:沒(méi)有寫(xiě)者時(shí)讀者才能讀,沒(méi)有讀者時(shí)寫(xiě)者才能寫(xiě)

    • 寫(xiě)-寫(xiě)互斥:沒(méi)有其它寫(xiě)者時(shí)才能寫(xiě)

  • 信號(hào)量方法

class Writer(){
    P(WriteMutex);
    write;
    V(WriteMutex);
}
class Reader(){
    P(CountMutex);
    if(Rcount ==0)
        P(WriteMutex);
    ++Rcount;
    V(CountMutex);
    
    read;
    
    P(CountMutex);
    --Rcount;
    if(Rcount ==0)
        V(WriteMutex);
    V(CountMutex);
}
  • 管程方法
AR = 0;   // # of active readers
AW = 0;   // # of active writers
WR = 0;   // # of waiting readers
WW = 0;   // # of waiting writers
Lock lock;
Condition okToRead;
Condition okToWrite;

//讀者
Private Database::StartRead() {
    lock.Acquire();
    while ((AW+WW) > 0) {
        WR++;
        okToRead.wait(&lock);
        WR--;
    }
    AR++;
    lock.Release();
}
Private Database::DoneRead() {
    lock.Acquire();
    AR--;
    if (AR ==0 && WW > 0) {
        okToWrite.signal();
    }
    lock.Release();
}
Public Database::Read() {
  //Wait until no writers;
  StartRead(); 
  read database;
  //check out – wake up waiting writers; 
  DoneRead(); 
}

//寫(xiě)者
Private Database::StartRead() {
    lock.Acquire();
    while ((AW+WW) > 0) {
        WR++;
        okToRead.wait(&lock);
        WR--;
    }
    AR++;
    lock.Release();
}
Private Database::DoneRead() {
    lock.Acquire();
    AR--;
    if (AR ==0 && WW > 0) {
        okToWrite.signal();
    }
    lock.Release();
}
Public Database::Read() {
  //Wait until no writers;
  StartRead(); 
  read database;
  //check out – wake up waiting writers; 
  DoneRead(); 
}
哲學(xué)家就餐問(wèn)題
  • 問(wèn)題描述

    • 5個(gè)哲學(xué)家圍繞一張圓桌而坐

      • 桌子上放著5支叉子

      • 每?jī)蓚€(gè)哲學(xué)家之間放一支

    • 哲學(xué)家的動(dòng)作包括思考和進(jìn)餐

      • 進(jìn)餐時(shí)需同時(shí)拿到左右兩邊的叉子

      • 思考時(shí)將兩只叉子放回原處

更多精彩,關(guān)注“咋家”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第10章:信號(hào)量與管程 信號(hào)量信號(hào)量使用互斥訪(fǎng)問(wèn)條件同步管程經(jīng)典同步問(wèn)題哲學(xué)家就餐問(wèn)題讀者-寫(xiě)者問(wèn)題 10.1 信...
    liuzhangjie閱讀 2,968評(píng)論 0 1
  • 18.1信號(hào)量 回顧 ■并發(fā)問(wèn)題 多線(xiàn)程并發(fā)導(dǎo)致資源競(jìng)爭(zhēng) ■同步概念 協(xié)調(diào)多線(xiàn)程對(duì)共享數(shù)據(jù)的訪(fǎng)問(wèn) 任何時(shí)刻只能有一...
    龜龜51閱讀 2,159評(píng)論 0 0
  • 線(xiàn)程同步(互斥鎖與信號(hào)量的作用與區(qū)別) “信號(hào)量用在多線(xiàn)程多任務(wù)同步的,一個(gè)線(xiàn)程完成了某一個(gè)動(dòng)作就通過(guò)信號(hào)量告訴別...
    勝浩_ae28閱讀 5,090評(píng)論 0 2
  • 文/白鷺 每年,我總是特別喜歡九月,大家都說(shuō)九月很符合我的氣質(zhì),因?yàn)槲沂蔷旁律?,微風(fēng)涼,白露生,所以給自己取了筆...
    白鷺姑娘閱讀 6,742評(píng)論 127 105
  • 21天E戰(zhàn)到底第一天學(xué)習(xí)打卡,今天是第二次學(xué)習(xí)“認(rèn)識(shí)Excel,突破理論”課程,時(shí)隔十天再次學(xué)習(xí)這個(gè)課程又有不同的...
    相信自己_d4c2閱讀 246評(píng)論 0 3

友情鏈接更多精彩內(nèi)容