2012-02-08 124 views
2

我正在學校項目上工作(解釋我在問題中的限制)。我的問題是如何在NACHOS中實現沒有信號量的鎖。雖然NACHOS的具體答案會很好,但我正在尋找的是朝正確方向推進。到目前爲止,根據我的理解,監視器使用使用信號量的鎖(真正的互斥鎖)。最初我們想用監視器替換信號量來實現鎖定,但是,這沒有意義。實現沒有信號量的鎖

+0

您允許禁用中斷嗎? – templatetypedef 2012-02-16 00:53:12

回答

0

您可能想要考慮忙等待並且不需要信號量的自旋鎖。但是,在單處理器中不使用自旋鎖。

0

鎖可以通過Thread:Sleep來實現。

class Lock { 
    public: 
    Lock(char* debugName);   // initialize lock to be FREE 
    ~Lock();    // deallocate lock 
    char* getName() { return name; } // debugging assist 

    void Acquire(); // these are the only operations on a lock 
    void Release(); // they are both *atomic* 

    bool isHeldByCurrentThread() { return (thread == currentThread); } // true if the current thread 
        // holds this lock. Useful for 
        // checking in Release, and in 
        // Condition variable ops below. 

    private: 
    char* name;    // for debugging 
    // plus some other stuff you'll need to define 
    Thread *thread;  //the thread who holds this lock 
    enum value {FREE, BUSY}; 
    List *queue; 
}; 

Lock::Lock(char* debugName):name(debugName), thread(NULL), value(FREE), queue(new List()) 
{ } 
Lock::~Lock() 
{ 
    delete queue; 
} 
void Lock::Acquire() 
{ 
    IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts 
    if (value == BUSY) { 
     queue->Append((void *)currentThread); 
     currentThread->Sleep(); 
    } 
    value = BUSY; 
    thread = currentThread; 
    (void) interrupt->SetLevel(oldLevel); // re-enable interrupts 
} 
void Lock::Release() 
{ 
    Thread *nextThread; 
    IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts 
    nextThread = (Thread *)queue->Remove(); 
    if (nextThread != NULL) // make thread ready, consuming the V immediately 
     scheduler->ReadyToRun(nextThread); 
    value = FREE; 
    (void) interrupt->SetLevel(oldLevel); // re-enable interrupts 
} 
0

首先檢查鎖的當前持有者是否是當前線程。然後使用中斷開關和睡眠來實現鎖定。線程從睡眠中醒來後,應該再次檢查鎖是忙還是空閒的,因爲喚醒一個線程只會將它傳遞給就緒隊列。在此線程可以獲取鎖之前,其他線程可能會同時獲取該鎖。

void Lock::Acquire() { 
    ASSERT(!isHeldByCurrentThread()); // cannot acquire a lock twice 

    IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts 
    while (freeOrBusy == 'b') { 
     queue->Append((void *)currentThread); 
     currentThread->Sleep(); 
    } 
    freeOrBusy = 'b'; 
    currentHolder = currentThread; 
    (void) interrupt->SetLevel(oldLevel); // re-enable interrupts 
} 

void Lock::Release() { 
    ASSERT(isHeldByCurrentThread()); 

    IntStatus oldLevel = interrupt->SetLevel(IntOff); 
    freeOrBusy = 'f'; 
    currentHolder = NULL; 

    Thread *thread = (Thread *)queue->Remove(); // "queue" is the list of threads waiting 
    if (thread != NULL) // make thread ready 
     scheduler->ReadyToRun(thread); 

    (void) interrupt->SetLevel(oldLevel); 

}