linux下互斥锁实现的简单的生产者消费者问题

这个程序实现的功能很简单,也算是入门linux下的多线程编程了吧~

其创造了两个生产者和一个消费者,两个生产者通过互斥锁实现同步,往缓冲区里放入数据,数据的值和其下标值一样,方便消费者的检验

消费者等到生产者放完数据后,从缓冲区中取出数据,并进行检验,看是否有出现差错,没有的话即实现了同步操作

/* include main */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define	MAXNITEMS 		10      //缓冲区大小为10
/*
	两个生产者,实现它们之间的同步  
	缓冲区内第一个位置放1,第二个位置放2这种
	一个消费者,检验其是否出错
*/

struct 
{
	pthread_mutex_t lock;
	int key;
	int value;
	int buff[MAXNITEMS];
}shared = {
	PTHREAD_MUTEX_INITIALIZER
};

//这样对结构体初始化

void * create_producer1()
{
	for(;;)
	{
		pthread_mutex_lock(&shared.lock);
		if(shared.key >= MAXNITEMS)
		{
			pthread_mutex_unlock(&shared.lock);
			printf("producer1: my function is over~\n"); 
			pthread_exit(NULL);

		}
		shared.buff[shared.key] = shared.value;
		printf("producer1 have put the data: %d\n",shared.value);
		shared.key ++;
		shared.value ++;
		pthread_mutex_unlock(&shared.lock);

	}

}


void * create_producer2()
{

	for(;;)
	{
		pthread_mutex_lock(&shared.lock);
		if(shared.key >= MAXNITEMS)
		{
			pthread_mutex_unlock(&shared.lock);
			printf("producer2: my function is over~\n");
			pthread_exit(NULL);

		}
		shared.buff[shared.key] = shared.value;
		printf("producer2 have put the data: %d\n",shared.value);
		shared.key ++;
		shared.value ++;
		pthread_mutex_unlock(&shared.lock);

	}

	
}

void * create_consumer()
{

	for(int i = 0;i < 10;i++)
	{
		if(shared.buff[i] != i)
		{
			printf("buff[%d] = %d was wrong!\n", i , shared.buff[i]);
			
		}
	}


	printf("All have scanned!\n");
	return (NULL);
}



int main(int argc, char const *argv[])
{
	pthread_t tid1,tid2;
	pthread_t consumer_tid;



	printf("I will create two producers and one consumers\n");

	if(pthread_create(&tid1,NULL,create_producer1,NULL) != 0)
		printf("create producer1 failed!\n");
	else
		printf("producer1 has been create!\n");



	if(pthread_create(&tid2,NULL,create_producer2,NULL) != 0)
		printf("create producer2 failed!\n");
	else
		printf("producer2 has been create!\n");

//等待生产者线程结束
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	if(pthread_create(&consumer_tid,NULL,create_consumer,NULL) != 0)
		printf("create consumer failed!\n");
	else
		printf("consumer has been create and begin check out the buff...\n");


	pthread_join(consumer_tid,NULL);


	return 0;
}

运行截图:

生产者消费者1.0

实现进阶:
我们上一个实现中,规定了当生产者往缓冲区里放完数据后,消费者才去检验,所以就不用考虑生产者和消费者之间的同步问题。这次我们让生产者和消费者一起产生,然后让消费者等待生产者放入其想要监测的数据,即加上这么一段等待的代码

void consumer_wait(int i)
{
	for(;;)
	{
		pthread_mutex_lock(&shared.lock);

		if (i < shared.key)
		{
			pthread_mutex_unlock(&shared.lock);
			return;
		}

		pthread_mutex_unlock(&shared.lock);
	}

}

消费者的代码改为如下:

void * create_consumer()
{

	for(int i = 0;i < 10;i++)
	{
		consumer_wait(i);
		if(shared.buff[i] != i)
		{
			printf("buff[%d] = %d was wrong!\n", i , shared.buff[i]);
			
		}
	}


	printf("All have scanned!\n");
	return (NULL);
}

实现进阶二:

由于上一个实现中,当消费者在等待生产者的时候,它是一遍一遍的轮询,这样很消耗计算机内存资源,我们为了更高效一点,引入信号量。

linux中每一个信号量都关联一个互斥锁,所以我们建立两个结构体,一个存放信号量和互斥锁,还又信号量判断nready,nready=0则消费者阻塞,nready=1则消费者接触堵塞。,一个结构体存放下一个要放入缓冲区下标,还有数值,还有防止冲突的互斥锁。

两个结构体:其自动初始化,也可以手动初始化
struct 
{
	pthread_mutex_t lock;
	int key;
	int value;
}put = {
	PTHREAD_MUTEX_INITIALIZER
};

//通过信号量来控制消息的传递  每一个信号量关联着一个互斥锁
struct {

	pthread_mutex_t mutex;
	pthread_cond_t cond;
	int nready;
} nready = {
	PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER
};

全部代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define	MAXNITEMS 		10      //缓冲区大小为10
/*
	两个生产者,实现它们之间的同步  
	缓冲区内第一个位置放1,第二个位置放2这种
	一个消费者,检验其是否出错
	生产者消费者一起创建 还要保证生产者和消费者之间的同步
	还要防止再期待的条件尚未达到的时候不断轮询造成资源浪费,所以要有信号量
*/

int buff[MAXNITEMS];


struct 
{
	pthread_mutex_t lock;
	int key;
	int value;
}put = {
	PTHREAD_MUTEX_INITIALIZER
};

//通过信号量来控制消息的传递  每一个信号量关联着一个互斥锁
struct {

	pthread_mutex_t mutex;
	pthread_cond_t cond;
	int nready;
} nready = {
	PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER
};

//这样对结构体初始化

//都要加上shared前缀,不要忘了!!!
//还忘记写循环了,没有循环放元素

void * create_producer1()
{
	for(;;)
	{
		pthread_mutex_lock(&put.lock);
		if(put.key >= MAXNITEMS)
		{
			pthread_mutex_unlock(&put.lock);//这里为shared.lock还要加&符号
			printf("producer1: my function is over~\n"); 
			pthread_exit(NULL);

		}
		buff[put.key] = put.value;
		printf("producer1 have put the data: %d\n",put.value);
		put.key ++;
		put.value ++;
		pthread_mutex_unlock(&put.lock);

		pthread_mutex_lock(&nready.mutex);
		if(nready.nready == 0)
			pthread_cond_signal(&nready.cond);
		nready.nready++;
		pthread_mutex_unlock(&nready.mutex);

	}

}


void * create_producer2()
{

	for(;;)
	{
		pthread_mutex_lock(&put.lock);
		if(put.key >= MAXNITEMS)
		{
			pthread_mutex_unlock(&put.lock);//这里为shared.lock还要加&符号
			printf("producer2: my function is over~\n"); 
			pthread_exit(NULL);

		}
		buff[put.key] = put.value;
		printf("producer2 have put the data: %d\n",put.value);
		put.key ++;
		put.value ++;
		pthread_mutex_unlock(&put.lock);

		pthread_mutex_lock(&nready.mutex);
		if(nready.nready == 0)
			pthread_cond_signal(&nready.cond);
		nready.nready++;
		pthread_mutex_unlock(&nready.mutex);

	}

	
}


void * create_consumer()
{

	for(int i = 0;i < 10;i++)
	{
		pthread_mutex_lock(&nready.mutex);
		while(nready.nready == 0)
				pthread_cond_wait(&nready.cond,&nready.mutex);
		nready.nready -- ;

		pthread_mutex_unlock(&nready.mutex);
		
		if(buff[i] != i)
		{
			printf("buff[%d] = %d was wrong!\n", i ,buff[i]);
			
		}
	}


	printf("All have scanned!\n");
	return (NULL);
}



int main(int argc, char const *argv[])
{
	pthread_t tid1,tid2;
	pthread_t consumer_tid;



	printf("I will create two producers and one consumers\n");

	if(pthread_create(&tid1,NULL,create_producer1,NULL) != 0)
		printf("create producer1 failed!\n");
	else
		printf("producer1 has been create!\n");



	if(pthread_create(&tid2,NULL,create_producer2,NULL) != 0)
		printf("create producer2 failed!\n");
	else
		printf("producer2 has been create!\n");


	if(pthread_create(&consumer_tid,NULL,create_consumer,NULL) != 0)
		printf("create consumer failed!\n");
	else
		printf("consumer has been create and begin check out the buff...\n");


//怎样等待线程结束呢。好像就直接这样接着写结束
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	pthread_join(consumer_tid,NULL);


	return 0;
}

运行截图为:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37414405/article/details/83615727
今日推荐