【发布时间】:2019-10-17 05:15:53
【问题描述】:
在多处理器系统上给出以下伪代码:
class SpinLock {
private:
int value = 0; // 0 = FREE; 1 = BUSY
public:
void acquire() {
while (test_and_set(&value)) // while BUSY
; // spin
}
void release() {
value = 0;
memory_barrier();
}
}
其中 test-and-set 指令以原子方式从内存中读取一个值到寄存器,并将值 1 写入该内存位置。
现在他们通过以下方式实现锁:
class Lock {
private:
int value = FREE;
SpinLock spinLock;
Queue waiting;
public:
void acquire();
void release();
}
Lock::acquire() {
spinLock.acquire();
if (value != FREE) {
waiting.add(runningThread);
scheduler.suspend(&spinLock);
// scheduler releases spinLock
} else {
value = BUSY;
spinLock.release();
}
}
void Lock::release() {
TCB *next;
spinLock.acquire();
if (waiting.notEmpty()) {
next = waiting.remove();
scheduler.makeReady(next);
} else {
value = FREE;
}
spinLock.release();
}
class Scheduler {
private:
Queue readyList;
SpinLock schedulerSpinLock;
public:
void suspend(SpinLock *lock);”
void makeReady(Thread *thread);
}
void
Scheduler::suspend(SpinLock *lock) {
TCB *chosenTCB;
disableInterrupts();
schedulerSpinLock.acquire();
lock->release();
runningThread->state = WAITING;
chosenTCB = readyList.getNextThread();
thread_switch(runningThread,
chosenTCB);
runningThread->state = RUNNING;
schedulerSpinLock.release();
enableInterrupts();
}
void
Scheduler::makeReady(TCB *thread) {
disableInterrupts();
schedulerSpinLock.acquire();
readyList.add(thread);
thread->state = READY;
schedulerSpinLock.release();
enableInterrupts();
}
我不明白这是如何工作的。假设我们在调用 acquire() 时位于线程 A 中,并且 Lock 由其他线程 B 拥有。
我们获取 Lock 对象的自旋锁,将线程添加到等待列表中,并以 Lock 的自旋锁作为参数调用 scheduler.suspend。 在suspend方法中我们会获取调度器的自旋锁,假设它是空闲的,那么我们释放Lock的自旋锁,将正在运行的线程A的状态变为等待,从就绪队列中获取一个线程C然后执行一个上下文切换。
我不明白调度程序的自旋锁现在是如何释放的。在上下文切换中,堆栈指针更改为新线程 C 的堆栈指针,也交换了寄存器,特别是指令指针,因此 thread_switch 之后的语句直到旧线程 C 再次分配 CPU 时间才执行,对吗?所以我们假设调度器的自旋锁不是空闲的,而是被线程 A 持有。
假设线程 B 释放它的锁。它获取Lock的自旋锁,它是空闲的,并且等待队列中至少有一个线程,即A。假设选择A作为下一个,所以我们以线程A为参数调用scheduler.makeReady。但是现在在 makeReady 内部有一个调用来获取调度程序的自旋锁,它没有被释放,因为我们在执行线程 A 时在 Scheduler::suspend() 内部调用 schedulerSpinlock.release() 之前执行了上下文切换。那么怎么能线程 A 现在释放调度器的自旋锁,如果我们不能再次运行它?
【问题讨论】:
标签: multithreading concurrency operating-system