这个程序实现的功能很简单,也算是入门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;
}
运行截图:
实现进阶:
我们上一个实现中,规定了当生产者往缓冲区里放完数据后,消费者才去检验,所以就不用考虑生产者和消费者之间的同步问题。这次我们让生产者和消费者一起产生,然后让消费者等待生产者放入其想要监测的数据,即加上这么一段等待的代码
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;
}
运行截图为: