执行结果是正确的。我们先将信号量的值设置为1,然后将f1、f2并发执行,这时如果f1先执行,执行p操作,s=0,进程继续执行,此时如果执行进程2,执行p操作,s=-1<0,进程就会被阻塞放入等待队列中,f1的进程就会继续执行,当执行到v操作,s=0,不符合执行条件,则唤醒等待队列中的f2的进程,当f2的v操作执行完,这时s=1可以通过,则进程执行完成。所以在f1进程执行过过程中,不管有多少进程执行了,都会被转到阻塞态,s可能会很小,但是在当前进程执行v操作时会不停唤醒等待队列中的进程直到s大于0,所以在当前进程执行时不会有其他的进程来执行,这样就实现了进程的互斥性。
这里我们所说的进程间的通信,指的就是进程能够一个一个来执行,不会“抢”,通过信号量还有PV操作,我们实现了进程的互斥性,就是进程间像是能够通信一样,当一个进程运行时,其他进程全部阻塞。
六、生产者、消费者问题生产者-消费者问题也称有限缓冲问题,是一个多线程同步的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
生产者、消费者问题有几种形式,我们来分别讨论:
(1)一个生产者、一个消费者,公用一个缓冲区
这里我们设置三个信号量s、empty、full,s表示缓冲区的个数,初值为1;empty表示缓冲区的大小,初值为20,即我们假设缓冲区最多能放20个产品;full表示缓冲区是否为空,初值为0。实现的程序如下:
程序中,我们用producer()来表示生产者,用consumer()来表示消费者,生产者生产一件产品要占用要判断缓冲区是否未满,即剩余空间empty减一之后是否还大于等于0,所以先对empty进行p操作,之后用p(&s)判断缓冲区是否被占用,再进行生产(product加一并输出)后用v操作释放缓冲区,再执行v操作对full加1判断是否大于0,即缓冲区是否为空,如果为不为空则继续执行,因为full的初值为0,而生产者进程执行的时间片完后轮到消费者进程,对full进行p操作是-1,消费者进程被堵塞再执行生产者进程,执行到v(&full)时,full加1变成0,所以唤醒消费者进程,p(&full),full变成-1,再被堵塞,执行生产者进程,所以生产者进程和消费者进程会不断交替执行。为了使产品累加起来便于观察,我用延时函数delay使生产者生产产品的周期比消费者消费产品的周期要短。我们来观察程序的执行过程: