使用信号量机制解决生产者消费者问题

生产者消费者问题是经典的同步问题,这篇文章用来记录一下如何使用信号量机制解决。

信号量机制(Semaphore)是解决同步问题常用解法,所谓信号量其实就代表着对应共享资源的数量。对于信号量只允许三种操作,分别是初始化、P操作、V操作。P、V操作都是具有原子性的。
P操作会减少信号量的值(假设一次减1),如果信号量成为负数,就代表着资源不够,调用线程会进入该信号量的等待队列,变为阻塞状态。
V操作会增加信号量的值(假设一次加1),并唤醒处于等待队列头部的线程。

信号量机制用法灵活,既可以用来实现互斥,也可以实现“线程一前一后执行”的同步关系。
下面讨论如何解决生产者消费者问题。

生产者消费者问题:多个生产者向产品队列中投放产品,多个消费者从产品队列中取出产品

分析该问题中存在的同步关系:
1.产品队列在同一时刻应该只能被一个线程访问,这是显而易见的。这里存在一个互斥关系,可以设置一个信号量mutex,且初始值为1(初值为1,且只允许在0,1之间变动,可实现线程互斥)
2.当产品队列中空位为0时,生产者不应该继续往队列中投放产品,应该等待消费者取出产品制造空位后,才能继续生产。这里存在“线程间一前一后执行”的同步关系,设置一个信号量empty,生产者每次生产之前需要对empty执行一次P操作,消费者每次消费之后对empty执行一次V操作。
3.当产品队列中产品数为0时,消费者不应该继续从队列中取出产品,应该等待生产者投放产品后,才能继续消费。这里存在“线程间一前一后执行”的同步关系,设置一个信号量filled,消费者每次消费之前需要对filled执行一次P操作,生产者每次生产之后对filled执行一次V操作。

下面为伪代码:

Product products[5]; //容量为5的产品队列
Semaphore mutex = 1; //用以实现互斥访问产品队列的信号量
Semaphore empty = 5; //初始时空位为5
Semaphore filled = 0; //初始时产品数为0

//生产者
void produce(){
	while (true) {
		...
		P(empty); 
		P(mutex);
		//
		//向产品队列投放产品
		//
		V(mutex);
		V(filled);
		...
	}
}

//消费者
void consumer(){
	while (true) {
		...
		P(filled); 
		P(mutex);
		//
		//向产品队列投放产品
		//
		V(mutex);
		V(empty);
		...
	}
}

你可能感兴趣的:(操作系统,操作系统,线程安全)