Сначала проверьте, является ли текущий держатель замка текущим потоком или нет.Затем используйте прерывание вкл-выкл и спать, чтобы добиться блокировки.После того, как поток выходит из спящего режима, он должен снова проверить, занята ли блокировка или свободна, потому что пробуждение потока только передает его в готовую очередь.Тем временем другой поток может снова получить блокировку, прежде чем этот поток сможет получить блокировку.
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);
}