先决条件—— 进程同步 , 监视器 , 读者作家问题 考虑到共享数据库,我们的目标是:
null
- 只有在没有写入程序的情况下,读卡器才能访问数据库。
- 只有在没有读卡器或写卡器的情况下,写卡器才能访问数据库。
- 一次只有一个线程可以操作状态变量。
解决方案的基本结构——
Reader() Wait until no writers Access database Check out – wake up a waiting writer Writer() Wait until no active readers or writers Access database Check out – wake up waiting readers or writer
–现在让我们假设一位作家是活跃的,读者和作家的混合体现在出现了。 下一个应该是谁? ——或者假设一位作家正在等待,无数读者不断出现。 对他们来说变得活跃公平吗? 因此,我们将实施一种来回形式的公平:
- 一旦有读者在等待,下一位读者就会进入。
- 如果一位作家正在等待,下一位作家将进入。
使用监控器实施解决方案:-
- 这些方法应该以互斥方式执行,即在每个时间点,最多一个线程可以执行其任何方法。
- 监视器还为线程提供了一种机制,使其在重新获得独占访问并恢复其任务之前,暂时放弃独占访问,以等待满足某些条件。
- 监视器还有一种机制,用于向其他线程发出信号,表明这些条件已经满足。
- 所以在这个实现中,仅仅相互排斥是不够的。尝试操作的线程可能需要等待,直到某个断言P为真。
- 当一个线程正在等待一个条件变量时,该线程不会被认为占用监视器,因此其他线程可能会进入监视器以更改监视器的状态。
代码–
// STATE VARIABLES // Number of active readers; initially = 0 int NReaders = 0; // Number of waiting readers; initially = 0 int WaitingReaders = 0; // Number of active writers; initially = 0 int NWriters = 0; // Number of waiting writers; initially = 0 int WaitingWriters = 0; Condition canRead = NULL; Condition canWrite = NULL; Void BeginWrite() { // A writer can enter if there are no other // active writers and no readers are waiting if (NWriters == 1 || NReaders > 0) { ++WaitingWriters; wait(CanWrite); --WaitingWriters; } NWriters = 1; } Void EndWrite() { NWriters = 0; // Checks to see if any readers are waiting if (WaitingReaders) Signal(CanRead); else Signal(CanWrite); } Void BeginRead() { // A reader can enter if there are no writers // active or waiting, so we can have // many readers active all at once if (NWriters == 1 || WaitingWriters > 0) { ++WaitingReaders; // Otherwise, a reader waits (maybe many do) Wait(CanRead); --WaitingReaders; } ++NReaders; Signal(CanRead); } Void EndRead() { // When a reader finishes, if it was the last reader, // it lets a writer in (if any is there). if (--NReaders == 0) Signal(CanWrite); } |
了解解决方案:-
- 它想要公平。
- 如果作者正在等待,读者就会排队。
- 如果读卡器(或另一个写卡器)处于活动状态或正在等待,写卡器将排队。
- 这在很大程度上是公平的,尽管一旦它让一个读者进来,它就让所有等待的读者同时进来,即使有些读者在其他等待的作者之后出现。
- 在“EndWrite”代码中(它表示可以在不检查等待写入程序的情况下写入)
- 在EndRead代码中(同样的事情)
- 在StartRead中(信号可以在末尾读取)
对于信号量,我们从未有过这种“公平”的解决方案。事实上,这是可以做到的,但代码是相当棘手的。在这里,简单的解决方案以理想的方式工作!监视器不太容易出错,也更容易理解。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END