高级操作系统——Nachos同步机制
nachos中有三種同步互斥機制:信號量,鎖,關系變量
信號量:
可以看到,信號量Semaphore里有一個隊列queue,用于存儲阻塞的線程。
接下來看看P,V操作
可以看到,關閉中斷后
如果value>0,那么while條件不成立跳出循環,value–表示取得所需資源,P操作結束。
如果value<0,那么進入while循環,將線程掛入隊列,再調用currentThread->Sleep();由以前的Lab知道sleep->run->switch切換進程。
但是這里是關中斷,屏蔽切換,所以接下來無計可施??
所以我們考慮到 IntStatus oldLevel = interrupt->SetLevel(IntOff);只是軟件層面的關中斷,對硬件不做影響。相當于若軟件程序如果想要中斷,可以if(statusIntOff)這樣判斷一下這與我們現實的屏蔽中斷完全不一樣==,所以我這樣認為,nachos里的開關中斷是沒有一點用處的!!!
如果上述成立,那么switch切換進程。當某個進程執行V()時,會喚醒一個在queue的sleep進程,并value++,此時Value》0,會讓某個線程跳出while循環并value–所以nachos真的只是一個玩具,這個Value難道不進行互斥控制嗎?
在介紹鎖之前,先給一個Exercise4的生產者消費者的實現
// threadtest.cc
// 條件變量實現生產者消費者問題
Condition* condc = new Condition(“ConsumerCondition”);
Condition* condp = new Condition(“ProducerCondition”);
Lock* pcLock = new Lock(“producerConsumerLock”);
int shareNum = 0; // 共享內容,生產+1,消費-1,互斥訪問
// lab3 條件變量實現生產者消費者問題
void Producer1(int val){while(1){pcLock->Acquire();while(shareNum >= N){ condp->Wait(pcLock);}++shareNum;condc->Signal(pcLock);pcLock->Release();sleep(val);} }void Customer1(int val){while(1){pcLock->Acquire();while(shareNum <= 0){ condc->Wait(pcLock);}--shareNum;condp->Signal(pcLock);pcLock->Release();} }void ThreadProducerConsumerTest1(){DEBUG('t', "Entering ThreadProducerConsumerTest1");Thread* p1 = new Thread("Producer1");Thread* p2 = new Thread("Producer2");p1->Fork(Producer1, 1);p2->Fork(Producer1, 3);Thread* c1 = new Thread("Consumer1");Thread* c2 = new Thread("Consumer2");c1->Fork(Customer1, 1);c2->Fork(Customer1, 2); }鎖
Lock::Lock(char* debugName) {name debugName;lock = new Semaphore(debugName, 1);owner NULL; } Lock::~Lock() {delete lock; } void Lock::Acquire() {IntStatus oldLevel = interrupt->SetLevel(IntOff);lock->P();owner = currentThread;(void)interrupt->SetLevel(oldLevel); } void Lock::Release() {IntStatus oldLevel = interrupt->SetLevel(IntOff);ASSERT(currentThread == owner);lock->v();owner = NULL;(void)interrupt->SetLevel(oldLevel); } bool Lock::isHeldByCurrentThread() {return currentThread == owner; }可以看到,nachos鎖實際上是Semaphore=1的封裝,本質上是互斥鎖
這里你需要想要多個用戶去競爭一把鎖多個生產者去競爭一個緩沖區
當Semaphore=1時,
對于Acquire,調用lock->P();P之前有提到過,是一個while循環。因為現在Semaphore=1所以會跳出循環并使得Semaphore=0。之后owner = currentThread;表明鎖的歸屬。
此時,對于其他Semaphore=0的線程,調用Acquire時候,也會調用lock->P(),此時因為Semaphore=0,所以都會進入Semaphore的queue并且睡眠。所以此時queue的線程是競爭鎖的線程(可能有多個)
而對于Release。其他沒有獲得鎖的線程如果調用此方法,因為ASSERT(currentThread == owner)所以會報錯。只有獲得鎖的線程能夠執行此方法lock->v()并且owner = NULL,V我們也提到過,是喚醒一個線程并讓value++,所以在queue中的睡眠線程會喚醒,并且獲得鎖。
綜上所述,鎖其實是互斥鎖,相當于p(s=1)的情況
條件變量
定于:同步機制,通常與互斥量一起使用。
條件變量允許線程由于一些暫時沒有達到的條件而阻塞。通常,等待另一個線程完成該線程所需要的條件。條件達到時,另外一個線程發送一個信號,喚醒該線程。
可以看到nachos中的條件變量有三個方法 wait,signal,broadcast
對于條件變量的理解,必須結合鎖。
在Wait中,我們看到conditionLock->Release()再執行conditionLock->Acquire();這是為什么呢?
看到前文的生產者消費者問題:有如下代碼
pcLock->Acquire();
while(shareNum >= N){
condp->Wait(pcLock);
}
這樣我們就可以理解為,首先多個生產者通過調用pcLock->Acquire();競爭鎖鎖理解成資源吧,而鎖只有一個,所以此時只有一個線程能夠進入while,如果shareNum >= N就是說緩沖區滿了,就會調用condp->Wait(pcLock);。在wait里,我們首先釋放鎖以便讓其他生產者能夠獲得鎖資源這里其實就是讓更多生產者進入while然后發現滿了進入sleep的queue,然后queue->Append(currentThread);加入到queue中之后sleep,此時切換其他線程。而有朝一日他被喚醒時候,會從sleep開始執行,重新去conditionLock->Acquire();以獲得生產的資格。之后便執行剩余的代碼。
同樣的,因為滿足了條件,所以調用Signal,喚醒了在queue上的某個線程。==這里無法理解為什么要ASSERT(conditionLock->isHeldByCurrentThread()); ==
如果是調用Broadcast,那么就是喚醒所有在queue上的線程
從上述我們可以得到理解,nachos里所有線程分為四個部分:
1:正在執行的線程currentThread
2:就緒的線程 scheduler的list,由鏈表進行控制
3:阻塞的線程,在Semaphore或者Condition里的queue控制
4:終止的線程,threadToBeDestroyed
其他線程如果沒有數據結構進行存儲,則over
以上就是理解,并且包含exercise2,3,4的代碼。
Challenge 1 實現barrier
barrier是Linux中的屏障機制。指的是必須所有線程都到達某一點后,才可以繼續執行。如果存在線程還沒有到達,則其他線程必須等待
Condition barrCond = new Condition(“BarrierCond”);
Lock* barrLock = new Lock(“BarrierLock”);
int barrierCnt = 0;
// 當且僅當barrierThreadNum個線程同時到達時才能往下運行
const int barrierThreadNum = 5;
總結
以上是生活随笔為你收集整理的高级操作系统——Nachos同步机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行银联支付系统demo
- 下一篇: 极域电子书包课堂管理系统怎么控屏_极域电