一、同步和互斥的概念
什么是同步?什么是互斥?
同步是一种时序关系。如规定了进程1处理完事情A后,进程2才能处理事情B,经典的同步问题是生产者和消费者间的同步.
互斥描述的是一种独占关系.如任一时刻,进城1和进程2中只能有一个写文件C.
有人说互斥是一种特殊的同步,同步是一种更为复杂的互斥关系(见" http//topic.csdn.net/t/20020711/17/867228.html"),但我不这么认为!
首先上面的言论是矛盾的,如果A和B互相包含,那A只能等于B,而同步和互斥显然是不等的。从前面的描述可以看出,同步和互斥是你中有我,我中有你的关系。当然如果你要从更广义地角度来说互斥是一种特殊的同步,我也没办法,毕竟我们的程序正确运行的前提就是同步。
二、生产者和消费者的问题分析
生产者和消费者的解答网络上有多种线程版本,但却没看到进程版本,所以我就来填补这一“空白”了。PS:使用进程版本的另一个重要原因是,想顺便复习下共享内存。
我们使用信号量来同步,用一个整型数组来当缓冲区。很显然这两者都要能够在各生产者和消费者进程间全局可见,所以我们用共享内存来实现他们。
生产者和消费者问题从易到难有三种。
1. 一个生产者和一个消费者,公用一个缓冲区
解决办法,定义两个信号量。
empty:表示缓冲区是否为空,初值为1,生产者用它来判断缓冲区是否可写。
full:表示缓冲区是否为满,初值为0,消费者用它来判断缓冲区是否可读。
producer(生产者)的伪码:
while(1)
{
P(empty);
写缓冲区;
V(full);
}
consumer(消费者)的伪码:
while(1)
{
P(full);
写缓冲区;
V(empty);
}
2. 一个生产者和一个消费者,公用m个环形缓冲区
分析过程与第一种情况类似,直接看伪码。
producer(生产者)的伪码:
while(1)
{
P(empty); /* empty初值为m */
写第in个缓冲区; /* in用来指示当前的第一个可写的缓冲区的下标,初值设为0。 */
in = (in+1)%m;
V(full);
}
consumer(消费者)的伪码:
while(1)
{
P(full); /* full初值为0 */
读第out个缓冲区; /* out用来指示当前的第一个可读的缓冲区的下标,初值设为0。 */
out = (out+1)%m;
V(empty);
}
3. 一组生产者和一组消费者,公用m个环形缓冲区
相比第2种情况,我们所要做的是用两个互斥变量mutex_producer和mutex_consumer,来实现各生产者间、各消费者间互斥地访问某个缓冲区。
producer(生产者)的伪码:
while(1)
{
P(empty); /* empty初值为m */
P(mutex_producer);
写