文档介绍:实验三
学会运用实验二中实现的工具来实现一些多线程并发问题。
EventBarrier:EventBarrier与某个事件相联系。事件有signaled和unsignale两种状态。线程想通过事件时必须等待事件被另外线程 signal。只有当所有进入事件的线程完成动作时发出signal的线程才将事件状态设为unsignaled
AlarmClock:AlarmClock让某个线程停止指定时间单位。当事件到达时重新将线程放入就绪队列。
Bridge:Bridge是一个单行桥且最大允许3量车在桥上行驶。实现应解决注意公平性与饥饿问题。
Elevator:实现Elevator类,并解决3个并发问题
a)一个电梯,电梯容量无限。
b)一个电梯,电梯容量有限。
c)多个电梯。
EventBarrier
enum BarrierStatus { unsignaled, signaled } ;
class EventBarrier{
public:
EventBarrier() ;
~EventBarrier() ;
void Wait() ;
void Signal() ;
plete() ;
int Waiters() ;
private:
LockO *lock ;
ConditionO *conSignal ; //用于挂起和唤醒调用Signal()函数的线程。
ConditionO *plete ; //用于挂起和唤醒完成response 而处于等待别的事件response的线程
ConditionO *conWait ; //用于挂起和唤醒那些当事件处于unsignaled而调用Wait()的线程
BarrierStatus status ; //事件状态
int waiterNum ;
};
类定义:
主要函数void EventBarrier::Complete () {
lock->Acquire() ;
waiterNum-- ;
if (waiterNum == 0) {
conSignal->Signal(lock); //通知Signal线程全部事件已处理完
}
plete->Wait(lock) ; //等待其它线程response
lock->Release();
}
void EventBarrier::Wait() {
lock->Acquire();
waiterNum++ ;
if (status == signaled) {
//处于 signaled 状态,直接return
lock->Release();
return ;
}
//处于 unsignaled 状态
//等到处于Signaled状态为止。
conWait->Wait(lock);
lock->Release();
}
void EventBarrier::Signal (){
lock->Acquire();
status = signaled ;
conWait->Broadcast(lock);
//通知所有等待Event的事件
while (waiterNum != 0){
conSignal->Wait(lock);
//当还有事件没response时挂起
}
plete->Broadcast(lock);
//通知所有等待别的线程response的线程
status = unsignaled ;
lock->Release();
}
1)Wait(): 线程挂起待事件被 signal,当事件已经处于signaled状态时直接return
2)Signal(): 线程通知所有等待事件的线程。并且挂起等待所有调用Wait()的线程 结 plete()通知此线程(包括在挂起过程中调用Wait()的线程)。
plete():当所有Wait()plete后通知Signal线程,此线程已 经完成操作,并且的等地其它线程response。
测试结果:
测试中主线程来释放Signal信号。
另4个线程做为等待线程,名字分别为 Thread 1~4。
Thread 1,2在主线程Signal之前就调用Wait()函数,Thread 3,4在事件被标志Signaled 状态时才调用Wait()。最终结果如下图所示,事件在四个线程都response自后才改变 状态,四个线程个主线程都运行正