@yanglt7
2018-05-25T15:11:39.000000Z
字数 6669
阅读 1542
操作系统
10.1 信号量(Semaphore)
ClassSemaphore {int sem;WaitQueue q;}Semaphore :: P() {sem --;if (sem<0) {Add this thread t to q;block(P);}}Semaphore :: V() {sem ++;if (sem<=0) {Remove a thread t from q;wakeup(t);}}
10.2 信号量的使用
mutex = new Semaphore(1); //初始化mutex -> P(); //第一个线程进来之后,由1变成0,能进去;若第二个线程也想进入临界区,由0变成-1,在P操作进入等待状态critical section;mutex -> V(); //第一次线程执行结束,进行V操作,使信号量计数由-1变成0, 唤醒第二个进程,则第二个进程就会在第一个进程结束时进入临界区
condition = new Semaphore(0);//线程A 线程B...M...condition -> P();...N... //使用数据 ...X... //准备数据condition -> v();...Y...
生产者 -> 缓冲区 -> 消费者
CLass BoundedBuffer {mutex = new Semaphore(1);fullBuffers = new Semaphore(0);emptyBuffers = new Semaphore(n);}BoundedBuffer :: Deposit(c) {emptyBuffer -> P();mutex -> P();Add c to the buffer;mutex -> V();fullBuffers -> V();}BoundedBuffer :: Remove(c) {fullBuffer -> P();mutex -> P();Remove c from buffer;mutex -> V();emptyBuffers -> V();}
10.3 管程(Monitor)
注
- 一个线程在临界区执行,必须执行到它退出临界区,它才能放弃临界区的互斥访问,而管程允许在执行的过程当中,临时放弃。放弃之后其他线程就可进入管程区域
Class Condition {int numWaiting = 0;WaitQueue = q;}Condition :: wait(lock) {numWaiting ++;Add this thread t to q;release(lock);schedule();//need mutexrequire(lock);}Condition :: Signal() {if (numWaiting>0) {Remove a thread from q;wakeup(t);//need mutexnumWaiting --;}}
ClassBoundedBuffer {...Lock lock;int count = 0;Condition notFull,notEmpty;}BoundedBuffer :: Deposit(c) {lock -> Acquire();while (count == n)notFull.Wait(&lock);Add c to the buffer;count ++;notEmpty.Signal();lock -> Release();}BoundedBuffer :: Remove(c) {lock -> Acquire(c);while (count == 0)notEmpty.Wait(&lock);Remove c from buffer;count --;notFull.Signal();lock -> Release();}
l.acquire()...x.wait() //T1进入等待//T2进入管程 l.acquire()...x.Signal()...//T1退出管程 l.release()... //T1恢复管程执行l.release()
l.acquire()...x.wait() //T1进入等待//T2进入管程 l.acquire()...//T2进入等待 x.Signal()... //T1恢复管程执行l.release() //T1结束... //T2恢复管程执行l.release()
Hoare 管程
Hansen 管程和Hoare 管程区别
Hansen-style:Deposit() {lock -> acquire();while (count == n) {notFull.Wait(&lock);}Add thing;count ++;notEmpty.Signal();lock -> Release();}Hoare-style:Deposit() {lock -> acquire();if (count == n) {notFull.Wait(&lock);}Add thing;count ++;notEmpty.Signal();lock -> Release();}
10.4 经典同步问题
(一)哲学家就餐问题
5个哲学家围绕着一张圆桌而坐
哲学家的动作包括思考和进餐
如何保证哲学家们的动作有序进行?
#define N 5 //哲学家个数semaphore fork[5]; //信号量初值为1void philosopher(int i) //哲学家编号:0-4while (TRUE){think(); //哲学家在思考P(fork[i]); //去拿左边的叉子P(fork[(i+1)%N]); //去拿右边的叉子eat(); //吃面条中V(fork[i]); //放下左边的叉子V(fork[(i+1)%N]); //放下右边的叉子}
#define N 5 //哲学家个数semaphore fork[5]; //信号量初值为1semaphore mutex; //互斥信号量,初值为1void philosopher(int i) //哲学家编号:0-4while (TRUE){think(); //哲学家在思考P(mutex); //进入临界区,任一时刻只能有一个进程申请到二进制信号量P(fork[i]); //去拿左边的叉子P(fork[(i+1)%N]); //去拿右边的叉子eat(); //吃面条中V(fork[i]); //放下左边的叉子V(fork[(i+1)%N]); //放下右边的叉子V(mutex); //退出临界区}
#define N 5 //哲学家个数semaphore fork[5]; //信号量初值为1void philosopher(int i) //哲学家编号:0-4while (TRUE){think(); //哲学家在思考if (i%2 == 0) {P(fork[i]); //去拿左边的叉子P(fork[(i+1)%N]); //去拿右边的叉子} else {P(fork[(i+1)%N]); //去拿右边的叉子P(fork[i]); //去拿左边的叉子}eat(); //吃面条中V(fork[i]); //放下左边的叉子V(fork[(i+1)%N]); //放下右边的叉子}
(二)读者-写者问题
共享数据的两类使用者
读者-写者问题描述:对共享数据的读写
“读-读”允许
“读-写”互斥
“写-写”互斥
用信号量描述每个约束
信号量WriteMutex
读者计数Rcount
信号量CountMutex
//WriterP(WriteMutex);write;V(WriteMutex);
//ReaderP(CountMutex);if(Rcount == 0) //第一个读者才需要申请读写互斥信号量,后来读者只需读者计数器加1P(WriteMutex);++ Rcount;V(CountMutex);read;P(CountMutex);-- Rcount;if(Rcount == 0) //只有最后一个读者才需要释放读写互斥信号量、V(WriteMutex);V(CountMutex);
Database :: Read() {Wait until no writers;read database;check out - wake up waiting writers;}Database :: Write() {Wait until no readers/writers;write database;check out - wake up waiting readers/writers;}
AR=0; //# of active readersAW=0; //# of active writers// 只有一个>0WR=0; //# of waiting readersWW=0; //# of waiting writers//可能都>0Lock lock;Condition okToRead;Condition okToWrite;
AR=0; //# of active readersAW=0; //# of active writersWR=0; //# of waiting readersWW=0; //# of waiting writersLock lock;Condition okToRead;Condition okToWrite;
Public Database :: Read() {//Wait until no writers;StartRead();read database;//check out - wake up waiting writers;DoneRead();}
Private Database :: StartRead() {lock.Acquire();while ((AW+WW)>0) { //条件决定了优先策略WR++;okToRead.wait(&lock);WR--;}AR++;lock.Release();}
Private Database :: DoneRead() {lock.Acquire();AR--;if ((AR==0 && WW)>0) { //条件决定了优先策略okToWrite.signal();}lock.Release();}
AR=0; //# of active readersAW=0; //# of active writersWR=0; //# of waiting readersWW=0; //# of waiting writersLock lock;Condition okToRead;Condition okToWrite;
Public Database :: Write() {//Wait until no readers/writers;StartWrite();write database;//check out - wake up waiting readers/writers;DoneWrite();}
Private Database :: StartWrite() {lock.Acquire();while ((AW+AR)>0) {WW++;okToWrite.wait(&lock);WW--;}AW++;lock.Release();}
Private Database :: DoneWrite() {lock.Acquire();AW--;if (WW>0) {okToWrite.signal();} else if (WR>0) {okToRead.broadcast();}lock.Release();}