在使用线程实现消费者生产者模型前,简单介绍一下线程的概念。
线程是进程的一个实体,对于进程而言,进程是程序资源分配的最小单元,这在之前提及过;而对于线程,它是程序执行的最小单元,即CPU调度和分派的基本单位,它附属于进程,同样也能独立运行。关于资源分配上,线程基本不拥有系统资源,只拥有运行中必不可少的一些资源如程序计数器,栈等。
对于线程同样有互斥和同步问题,互斥是多个线程之间操作同个共享数据时使某个线程操作,而其他的线程阻塞,直到资源解锁才能访问。同步则是令线程间按一定的顺序去运行。下面的模型就是采用同步机制使一个线程作为生产者,向全局字符数组写入数据,而另一个线程作为消费者,从数组中读取数据,通过两个信号量的P、V操作实现两线程的顺序先后,两者间为“先生产再消费”,即同步来实现。
具体实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define TEXT_SZ 1024
sem_t sem1;
sem_t sem2;
char text[TEXT_SZ];
void *write(void *text) //生产者数据输入函数
{
while(1)
{
sem_wait(&sem1); //信号量sem1 p操作
printf("(producer) write some text:");
if(fgets((char *)text, TEXT_SZ, stdin) == NULL) //写数据到全局数组
{
printf("write error!\n");
exit(1);
}
if(strncmp((char *)text,"end",3) == 0) //输入end退出线程1
{
sem_post(&sem2); //信号量sem2 v操作
break;
}
sem_post(&sem2); //信号量sem2 v操作
}
}
void *read(void *text) //消费者读取数据函数
{
while(1)
{
sem_wait(&sem2); //信号量sem2 p操作
printf("(customer) read the text:%s\n",(char *)text); //输出读到的数据
if(strncmp((char *)text,"end",3) == 0) //读取到end,退出线程2
{
sem_post(&sem1); //信号量sem1 v操作
break;
}
sem_post(&sem1); //信号量sem1 v操作
}
}
int main()
{
pthread_t thread1;
pthread_t thread2;
int ret1;
int ret2;
if(sem_init(&sem1,0,1) == -1) //初始化信号量sem1
{
printf("init sem1 error!\n");
exit(1);
}
if(sem_init(&sem2,0,0) == -1) //初始化信号量sem2
{
printf("init sem2 error!\n");
exit(1);
}
if(memset(text,0,sizeof(text)) == NULL)
{
printf("memset error!\n");
exit(1);
}
ret1 = pthread_create(&thread1,NULL,(void *)write,(void *)text);//创建线程1
if(ret1 < 0)
{
printf("thread1 create error!\n");
exit(1);
}
ret2 = pthread_create(&thread2,NULL,(void *)read,(void *)text);//创建线程2
if(ret2 < 0)
{
printf("thread2 create error!\n");
exit(1);
}
pthread_join(thread1,NULL); //等待线程1退出
pthread_join(thread2,NULL);//等待线程2退出
if(sem_destroy(&sem1) == -1) //删除信号量sem1
{
printf("delete sem1 error!\n");
exit(1);
}
if(sem_destroy(&sem2) == -1) //删除信号量sem2
{
printf("delete sem2 error!\n");
exit(1);
}
return 0;
}