Linux实验报告 消费者与生产者 多线程
- 格式:doc
- 大小:420.50 KB
- 文档页数:7
实验目标在本次实验中,使用信号量,编写一段程序解决生产者/消费者同步问题。
完成本次试验,理解Nachos的信号量是如何实现的生产者/消费者问题是如何用信号量实现的在Nachos中是如何创建并发线程的在Nachos下是如何测试和debug的实验环境Linux关键源代码注释Ringring与slot的关系如图所示,在prodcons++中,定义ring的BUFF_SIZE大小为3.生产者nempty->P();查看buffer是否有空,if nempty>0,nempty=nempty -1(用nempty代替nempty.value,下nfull同).mutex->P();加锁.向ring中放入message信息.mutex->V();解锁.nfull->V();通知消费者buffer有新信息,nfull=nfull+1.关键代码如下:voidProducer(_int which){int num;slot *message = new slot(0,0);//建立slot实例,此信息message将被放到ring buffer里。
每个信息message有一个id和一个value。
//每个生产者产生的商品的个数必须使用N_MESSG限定,否则程序没有结束for (num = 0; num < N_MESSG ; num++) {message->thread_id=which; //producer的idmessage->value=num; //产生的message的编号nempty->P();mutex->P();ring->Put(message);mutex->V();nfull->V();}}消费者nfull->P();查看buffer中是否有信息,if nfull>0,nfull-1.mutex->P();加锁.从ring buffer中取出信息.mutex->V();解锁.nempty->V();通知生产者bufferr有空nempty=nempty+1.关键代码如下:voidConsumer(_int which){char str[MAXLEN];char fname[LINELEN];int fd;slot *message = new slot(0,0);// to form a output file name for this consumer thread.// all the messages received by this consumer will be recorded in // this file.sprintf(fname, "tmp_%d", which);// create a file. Note that this is a UNIX system call.if ( (fd = creat(fname, 0600) ) == -1){perror("creat: file create failed");Exit(1);}//不需要规定每个消费者消费的商品的个数for (; ; ) {nfull->P();mutex->P();ring->Get(message);mutex->V();nempty->V();// form a string to record the messagesprintf(str,"producer id --> %d; Message number --> %d;\n",message->thread_id,message->value);// write this string into the output file of this consumer.// note that this is another UNIX system call.if ( write(fd, str, strlen(str)) == -1 ) {perror("write: write failed");Exit(1);}}}生产者/消费者问题的解决mutex = new Semaphore("mutux",1);信号量初始化为1,才能起到加锁功能nfull = new Semaphore("full",0);nfull的大小在生产者没生产前为0nempty = new Semaphore("empty",BUFF_SIZE);nempty的大小应该为buffer的大小创建线程生成一个生产者的代码:producers[i] = new Thread(prod_names[i]);producers[i] -> Fork(Producer,i);关键代码如下:voidProdCons(){int i;//建立信号量mutex = new Semaphore("mutux",1);nfull = new Semaphore("full",0);nempty = new Semaphore("empty",BUFF_SIZE);// 建立ring buffer,大小为BUFF_SIZEring = new Ring(BUFF_SIZE);// 建立并唤醒N_PROD个生产者线程for (i=0; i < N_PROD; i++){sprintf(prod_names[i], "producer_%d", i);//使用prod_names[i]创建线程producers[i] = new Thread(prod_names[i]);//行为为Producer定义,i为Producer参数producers[i] -> Fork(Producer,i);};// 建立并唤醒N_CONS 个消费者线程for (i=0; i < N_CONS; i++){sprintf(cons_names[i], "consumer_%d", i);//使用cons_names[i]创建线程consumers[i] = new Thread(cons_names[i]);//定义行为为Consumer,i为Consumer参数consumers[i] -> Fork(Consumer,i);};}调试记录源代码中exit(0)没有大写,增加了许多无谓的劳动。
实验报告
./clone输出结果:
实验讨论:
由程序1结果可知,使用fork()语句创建的子进程与其父进程具有相对独立的地址空间,在此解决生产者-消费者问题里,可以采用pipe()进行通讯。
子进程复制了父进程的打开文件表,所以pipe()所建立的通信管道可被子进程继承,生产和消费进程可以通过对同一通信管道文件的读书进行通讯。
由程序2结果可知:clone()语句在创建进程时,可通过参数设定子进程与父进程是否共享存储空间,从而可以创建真正意义上的程序。
生产者和消费者进程共享内在,从而可以通过共享交换数据。
但多个进程共享共存需要互斥机制。
三.实验流程图
程序二流程图:
基于clone()系统调用
父进程:
生产者子进程(Producer):。
案例10:生产者-消费者模型是线程同步中的一个经典案例。
假设有两个线程,这两个线程同时操作一个共享资源(一般称为汇聚),其中一个模拟生产者行为,生产共享资源,当容器存满时,生产者无法向其中放入产品;另一个线程模拟消费者行为,消费共享资源,当产品数量为0时,消费者无法获取产品,应阻塞等待。
显然,为防止数据混乱,每次只能由生产者、消费者中的一个,操作共享资源。
本案例要求使用程序实现简单的生产者-消费者模型(可假设容器无限大)。
案例实现如下:1#include <stdio.h>2#include <stdlib.h>3#include <unistd.h>4#include <pthread.h>5struct msg {6 struct msg *next;7 int num;8};9struct msg *head;10pthread_cond_t has_product = PTHREAD_COND_INITIALIZER; //初始化条件变量11pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //初始化互斥锁12//消费者13void *consumer(void *p)14{15 struct msg *mp;16 for (;;) {17 pthread_mutex_lock(&lock); //加锁18 //若头结点为空,表明产品数量为0,消费者无法消费产品19 while (head == NULL) {20 pthread_cond_wait(&has_product, &lock); //阻塞等待并解锁21 }22 mp = head;23 head = mp->next; //模拟消费一个产品24 pthread_mutex_unlock(&lock);25 printf("-Consume ---%d\n", mp->num);26 free(mp);27 sleep(rand() % 5);28 }29}30//生产者31void *producer(void *p)32{33 struct msg *mp;34 while (1) {35 mp = malloc(sizeof(struct msg));36 mp->num = rand() % 1000 + 1; //模拟生产一个产品37 printf("-Produce ---%d\n", mp->num);38 pthread_mutex_lock(&lock); //加锁39 mp->next = head; //插入结点(添加产品)40 head = mp;41 pthread_mutex_unlock(&lock); //解锁42 pthread_cond_signal(&has_product); //唤醒等待在该条件变量上的一个线程43 sleep(rand() % 5);44 }45}46int main(int argc, char *argv[])47{48 pthread_t pid, cid;49 srand(time(NULL));50 //创建生产者、消费者线程51 pthread_create(&pid, NULL, producer, NULL);52 pthread_create(&cid, NULL, consumer, NULL);53 //回收线程54 pthread_join(pid, NULL);55 pthread_join(cid, NULL);56 return 0;57}。
Linux⽣产者消费者简单例⼦学习#if 0Linux实现⽣产者消费者模型1. 防⽌虚假唤醒2. 唤醒线程的时机很重要,否则会导致线程多次访问锁,影响性能#endif#include <unistd.h>#include <stdio.h>#include <iostream>#include <pthread.h>using namespace std;int g_value = 0;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* consumer1(void* arg){printf("consumer[%d] begin consume.\n", (int)(*((int*)(arg))));pthread_mutex_lock(&mutex);printf("consumer[%d] pthread_mutex_lock.\n", (int)(*((int*)(arg))));while (g_value <= 0) {//防⽌虚假唤醒printf("consumer[%d] begin wait.\n", (int)(*((int*)(arg))));int ret = pthread_cond_wait(&cond, &mutex);if (ret) {printf("pthread_cond_wait error ret[%d].\n", ret);return NULL;}printf("consumer[%d] end wait.\n", (int)(*((int*)(arg))));}--g_value;printf("consumer[%d] g_value:[%d].\n", (int)(*((int*)(arg))), g_value);pthread_mutex_unlock(&mutex);printf("consumer[%d] pthread_mutex_unlock.\n", (int)(*((int*)(arg))));return NULL;}void* consumer2(void* arg){printf("consumer[%d] begin consume.\n", (int)(*((int*)(arg))));pthread_mutex_lock(&mutex);printf("consumer[%d] pthread_mutex_lock.\n", (int)(*((int*)(arg))));while (g_value <= 0) {//防⽌虚假唤醒printf("consumer[%d] begin wait.\n", (int)(*((int*)(arg))));int ret = pthread_cond_wait(&cond, &mutex);if (ret) {printf("pthread_cond_wait error ret[%d].\n", ret);return NULL;}printf("consumer[%d] end wait.\n", (int)(*((int*)(arg))));}--g_value;printf("consumer[%d] g_value:[%d].\n", (int)(*((int*)(arg))), g_value);pthread_mutex_unlock(&mutex);printf("consumer[%d] pthread_mutex_unlock.\n", (int)(*((int*)(arg))));return NULL;}void* producer(void* arg){cout << "producer begin product." << endl;pthread_mutex_lock(&mutex);printf("producer pthread_mutex_lock.\n");++g_value;cout << "producer g_value: " << g_value << endl;if (g_value > 0) {cout << "producer begin pthread_cond_broadcast." << endl;int ret = pthread_cond_broadcast(&cond);if (ret) {printf("pthread_cond_broadcast error ret[%d].\n", ret);return NULL;}cout << "producer end pthread_cond_broadcast." << endl;}printf("producer begin pthread_mutex_unlock.\n");int ret = pthread_mutex_unlock(&mutex);if (ret) {printf("pthread_mutex_unlock error ret[%d].\n", ret);return NULL;}printf("producer end pthread_mutex_unlock.\n");return NULL;}int join(pthread_t tid, void **retval){int ret = pthread_join(tid, retval);if (ret) {return ret;}else {return0;}}int main(){pthread_t tid_consumer[2] = {0};pthread_t tid_producer = 0;int ret = -1;int _consumer1 = 1;ret = pthread_create(&tid_consumer[0], NULL, &consumer1, (void*)(&_consumer1)); if (ret) {printf("pthread_create error ret[%d].\n", ret);return -1;}sleep(1);int _consumer2 = 2;ret = pthread_create(&tid_consumer[1], NULL, &consumer2, (void*)(&_consumer2)); if (ret) {printf("pthread_create error ret[%d].\n", ret);return -1;}sleep(5);ret = pthread_create(&tid_producer, NULL, &producer, NULL);if (ret){printf("pthread_create error ret[%d].\n", ret);return -1;}sleep(2);for (int i = 0; i < sizeof(tid_consumer)/sizeof(tid_consumer[0]); ++i){ret = join(tid_consumer[i], NULL);if (ret) {printf("join error ret[%d].\n", ret);}}ret = join(tid_producer, NULL);if (ret) {printf("join error ret[%d].\n", ret);return -1;}printf("pthread join success.\n");return0;}。
实验课程:操作系统实验实验编号:实验名称:生产者消费者算法实验人员:实验日期:上交日期:实验室:实验评价:一、目的和要求生产者消费者算法是操作系统中很重要的同步算法,通过本实验加深对互斥信号量和同步信号量的理解,掌握如何用信号量机制实现生产者消费者之间的同步算法。
二、实验内容运用高级语言模拟实现生产者消费者算法,要求实现对缓冲池的互斥访问和生产者进程与消费者进程之间的同步,观察程序的运行情况并分析执行结果。
三、实验环境1.PC微机。
2.Windows 操作系统。
3.C/C++/VB开发集成环境。
四、实验结果1.程序源代码:生产者&消费者如下图:# include <stdio.h># include <stdlib.h># include <time.h># include <sys/types.h># include <pthread.h># include <semaphore.h># include <string.h># include <unistd.h>#define BUFFER_SIZE 5typedef int buffer_item;//semaphoressem_t empty, full, mutex;//bufferbuffer_item buffer[BUFFER_SIZE]; int in, out;//存储数据的结构体struct data {int id;int opTime;int lastTime;int productId;};//有限缓存插入--生产int insert_item(buffer_item item) {/* insert item into buffer */buffer[out] = item;out = (out + 1) % BUFFER_SIZE;return 0;}//有限缓存删除--消费int remove_item(buffer_item *item) {/* remove an object from buffer and then place it in item */ *item = buffer[in];in = (in + 1) % BUFFER_SIZE;return 0;}//生产者void *producer(void* param) {int productId = ((struct data*)param)->productId;int lastTime = ((struct data*)param)->lastTime;int id = ((struct data*)param)->id;free(param);sleep(opTime);sem_wait(&empty);sem_wait(&mutex);/* critical section *///add a iteminsert_item(productId);sleep(lastTime);printf("Thread %d: Producer produce %d\n", id, productId);sem_post(&mutex);sem_post(&full);pthread_exit(0);}//消费者void *consumer(void* param) {int opTime = ((struct data*)param)->opTime;int id = ((struct data*)param)->id;free(param);sleep(opTime);sem_wait(&full);sem_wait(&mutex);/* critical section *///remove a itembuffer_item item;remove_item(&item);sleep(lastTime);printf("Thread %d: Consumer consume %d\n", id, item);sem_post(&mutex);sem_post(&empty);pthread_exit(0);}int main() {//pthreadpthread_t tid; // the thread identifierpthread_attr_t attr; //set of thread attributes/* get the default attributes */pthread_attr_init(&attr);//initial the semaphoressem_init(&mutex, 0, 1);sem_init(&empty, 0, BUFFER_SIZE);sem_init(&full, 0, 0);in = out = 0;int id = 0;while(scanf("%d", &id) != EOF) {char role; //producer or consumerint opTime; //operating timeint lastTime; //run timeint productId; //product idscanf("%c%d%d", &role, &opTime, &lastTime);struct data* d = (struct data*)malloc(sizeof(struct data));d->id = id;d->opTime = opTime;d->lastTime = lastTime;if(role == 'P') {scanf("%d", &productId);d->productId = productId;pthread_create(&tid, &attr, producer, d);}else if(role == 'C')pthread_create(&tid, &attr, consumer, d);}//释放信号量sem_destroy(&mutex);sem_destroy(&empty);sem_destroy(&full);return 0;}---------------------2.实验报告。
实验三:生产者与消费者一、实验目的1.学习和掌握操作系统中进程之间的通信;2.理解和掌握使用信号量机制来是想进程之间的同步和互斥;3.学习使用创建文件对象,并利用文件映射对象来实现数据通信。
二、实验内容•一个大小为6的缓冲区,初始为空,每个缓冲区能存放一个长度若为10个字符的字符串。
•2个生产者–随机等待一段时间,往缓冲区添加数据,–若缓冲区已满,等待消费者取走数据后再添加–重复12次•3个消费者–随机等待一段时间,从缓冲区读取数据–若缓冲区为空,等待生产者添加数据后再读取–重复8次说明:•显示每次添加和读取数据的时间及缓冲区的状态•生产者和消费者用进程模拟,缓冲区用共享内存来实现三、实验环境1.Windows下:Windows8 ,Visual studio 20132.Linux下:Linux Ubuntu 4,gcc四、程序设计与实现1.Windows下:A.主要函数说明:(1)PROCESS_INFORMATIONStartClone(intnCloneID)功能:用来创建5个相同的进程,前两个为生产者,后三两个为消费者,赋予其不同的ID值,返回进程的信息。
(2)CreateSemaphore();功能:创建3个信号量:full,empty,mutex。
来互斥的访问缓冲区,实现通信。
(3)CreateFileMapping()功能:在当前运行的进程中创建文件映射对象,来模拟共享缓冲区MapViewOfFile()功能:在此文件映射上创建视图映射到当前应用程序的地址空间B.程序流程图实验代码如下://#include"stdafx.h"#include<stdio.h>#include<windows.h>#include<time.h>static HANDLE hMutexMapping=INVALID_HANDLE_VALUE;int num=0;HANDLE lpHandle[10];struct buf{int num;int read;int write;int buffer[5];};BOOL StartClone(){int i;BOOL bCreateOK;PROCESS_INFORMATION pi;TCHAR szFilename[MAX_PATH];GetModuleFileName(NULL,szFilename,MAX_PATH);TCHAR szCmdLine[MAX_PATH];for ( i = 0; i < 3; i++){sprintf(szCmdLine,"\"%s\" consumer %d",szFilename,i);STARTUPINFO si;ZeroMemory(reinterpret_cast<void*>(&si),sizeof(si)); si.cb=sizeof(si);bCreateOK=CreateProcess(szFilename,szCmdLine,NULL,NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi);if (!bCreateOK){return false;lpHandle[num]=pi.hProcess;num++;}for ( i = 0; i < 2; i++){sprintf(szCmdLine,"\"%s\" productor %d",szFilename,i);STARTUPINFO si;ZeroMemory(reinterpret_cast<void *>(&si),sizeof(si)); si.cb=sizeof(si);bCreateOK=CreateProcess(szFilename,szCmdLine,NULL,NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi);if (!bCreateOK)return false;}lpHandle[num]=pi.hProcess;num++;}return true;}void Parent(){printf("Creating the child process and waited child process to quit.\n");hMutexMapping=CreateMutex(NULL,true,"mutex");HANDLE hMapping=CreateFileMapping(NULL,NULL,PAGE_READWRITE,0,sizeof(LONG),"map");if (hMapping!=INVALID_HANDLE_VALUE){LPVOID pData=MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);if (pData!=NULL){ZeroMemory(pData,sizeof(LONG));}struct buf *pnData=reinterpret_cast<struct buf*>(pData);pnData->read=0;pnData->write=0;pnData->num=0;memset(pnData->buffer,0,sizeof(pnData->buffer)); UnmapViewOfFile(pData);}CreateSemaphore(NULL,3,3,"EMPTY");CreateSemaphore(NULL,0,3,"FULL");BOOL bCreateOK=StartClone();if (!bCreateOK){//printf("Create child process failed.\n");}else{//printf("Create child process success.\n");}ReleaseMutex(hMutexMapping);}void Productor(int n){int j;printf("Productor is running.\n");hMutexMapping=OpenMutex(MUTEX_ALL_ACCESS,true,"mutex");HANDLE hMapping=OpenFileMapping(FILE_MAP_ALL_ACCESS,NULL,"map");if (hMapping==INVALID_HANDLE_VALUE){printf("error\n");}HANDLE semEmpty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EMPTY");HANDLE semFull =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FULL");for (int i = 0; i < 6; i++){WaitForSingleObject(semEmpty, INFINITE);SYSTEMTIME st;GetSystemTime(&st);srand((unsigned)time(0));Sleep(rand()/6);WaitForSingleObject(hMutexMapping,INFINITE);LPVOID pFile=MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);if (pFile!=NULL){struct buf *pnData=reinterpret_cast<struct buf *>(pFile);pnData->buffer[pnData->write]=1;pnData->write=(pnData->write+1)%3;pnData->num++;printf("%02d:%02d:%02d 生产者[%d]生产成功缓冲区中剩余%d个 ",st.wHour,st.wMinute,st.wSecond,n,pnData->num);for (j = 0; j < 3; j++){printf("%d ",pnData->buffer[j]);}printf("\n");}UnmapViewOfFile(pFile);pFile=NULL;ReleaseSemaphore(semFull, 1, NULL);ReleaseMutex(hMutexMapping);}printf("生产者[%d]生产完毕\n",n);}void Consumer(int n){int j;printf("Consumer is running.\n");hMutexMapping=OpenMutex(MUTEX_ALL_ACCESS,true,"mutex");HANDLE hMapping=OpenFileMapping(FILE_MAP_ALL_ACCESS,NULL,"map");if (hMapping==INVALID_HANDLE_VALUE){printf("error\n");}HANDLE semEmpty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EMPTY");HANDLE semFull =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FULL");for (int i = 0; i < 4; i++){WaitForSingleObject(semFull, INFINITE);SYSTEMTIME st;GetSystemTime(&st);srand((unsigned)time(0));Sleep(rand()/6);WaitForSingleObject(hMutexMapping,INFINITE);LPVOID pFile=MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);if (pFile!=NULL){struct buf *pnData=reinterpret_cast<struct buf *>(pFile);pnData->buffer[pnData->read]=0;pnData->read=(pnData->read+1)%3;pnData->num--;printf("%02d:%02d:%02d 消费者[%d]消费成功缓冲区中剩余%d个 ",st.wHour,st.wMinute,st.wSecond,n,pnData->num);for (j = 0; j < 3; j++){printf("%d ",pnData->buffer[j]);}printf("\n");}UnmapViewOfFile(pFile);pFile=NULL;ReleaseSemaphore(semEmpty,1,NULL);ReleaseMutex(hMutexMapping);}printf("消费者[%d]消费完毕\n",n);}int main(int argc,char **argv){if (argc>1&&strcmp(argv[1],"productor")==0){Productor(atoi(argv[2]));}else if (argc>1&&strcmp(argv[1],"consumer")==0){Consumer(atoi(argv[2]));}else{Parent();WaitForMultipleObjects(num,lpHandle,true,INFINITE); }return 0;}Linux下代码:Windows运行截图:Linux下截图:。
嵌入式操作系统Linux实验报告专业:计算机科学与技术班级:13419011学号:1341901124姓名:武易组员:朱清宇实验一Linux下进程的创建一实验目的1.掌握Linux下进程的创建及退出操作2.了解fork、execl、wait、waitpid及之间的关系二实验内容创建进程,利用fork函数创建子进程,使其调用execl函数,退出进程后调用wait或waitpid清理进程。
三实验过程1.进程的创建许多进程可以并发的运行同一程序,这些进程共享内存中程序正文的单一副本,但每个进程有自己的单独的数据和堆栈区。
一个进程可以在任何时刻可以执行新的程序,并且在它的生命周期中可以运行几个程序;又如,只要用户输入一条命令,shell进程就创建一个新进程。
fork函数用于在进程中创建一个新进程,新进程是子进程。
原型如下:#include<sys/types.h> /* 提供类型pid_t的定义 */#include<unistd.h> /* 提供函数的定义 */pid_t fork(void);使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间fork系统调用为父子进程返回不同的值,fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:在父进程中,fork返回新创建子进程的进程ID;✓在子进程中,fork返回0;✓如果出现错误,fork返回一个负值;用fork创建子进程后执行的是和父进程相同的程序,子进程可以通过调用exec函数以执行另一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程(例如其m a i n函数)开始执行。
调用e x e c并不创建新进程,进程I D并未改变,只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。
e x e c函数原型execl,execlp,execle,execv,execve和execvp2.进程的退出一个进程正常终止有三种方式:由main()函数返回;调用exit()函数;调用_exit()或_Exit()函数。
#include<stdio.h>#include<pthread.h>#define MAX 30#define BUFFER_SIZE 20pthread_mutex_t the_mutex,the_main,the_p;pthread_cond_t condc,condp;int buffer[BUFFER_SIZE];int in=0;int out=0;int counter=0;int flg[30]={0};int k=0;int p=0;void *producer1(void* s){pthread_mutex_lock(&the_main);pthread_mutex_unlock(&the_main);int proid=(int)s;int i;for(i=1;i<=MAX;i++){pthread_mutex_lock(&the_mutex);while(counter==BUFFER_SIZE){printf("%d号生产者wait...\n",proid);pthread_cond_wait(&condp,&the_mutex);printf("%d号生产者唤醒...\n",proid);}buffer[in]=1;printf("%d号生产者生产1放入%d中\n",proid,in);in=(in+1)%BUFFER_SIZE;counter++;pthread_cond_signal(&condc);pthread_mutex_unlock(&the_mutex);}pthread_mutex_lock(&the_p);p++;printf("%d号生产者线程结束\n",proid);pthread_mutex_unlock(&the_p);return 0;}void *consumer1(void* s){pthread_mutex_lock(&the_main);pthread_mutex_unlock(&the_main);int conid=(int)s;int j=1;int k=0;while(1){pthread_mutex_lock(&the_mutex);if(p==30&&counter==0){pthread_mutex_unlock(&the_mutex);break;}// printf("p=%d counter=%d\n",p,counter);while(counter==0){if(p==30&&counter==0){pthread_mutex_unlock(&the_mutex);break;}printf(" %d号消费者wait...\n",conid); pthread_cond_wait(&condc,&the_mutex);printf("%d号消费者唤醒...\n",conid);}if(buffer[out]==4){printf("%d号消费者在%d处消费%d counter=%d p=%d\n",conid,out);buffer[out]=0;out=(out+1)%BUFFER_SIZE;counter--;pthread_cond_signal(&condp);}if(buffer[out]==1&&flg[conid]==0){flg[conid]=1;printf("%d号消费者在%d处消费%d counter=%d p=%d\n",conid,out);for(j=1;j<=29;j=j+2)if(flg[j]==1)k++;if(k==15){k=0;for(j=1;j<=29;j++)flg[j]=0;buffer[out]=0;out=(out+1)%BUFFER_SIZE;counter--;pthread_cond_signal(&condp);}elsek=0;}else{pthread_cond_signal(&condc);}pthread_mutex_unlock(&the_mutex);}printf("%d消费者线程结束\n",conid);pthread_exit(0);}int main(int argc,char **argv){int j;pthread_t pro[31],con[31];pthread_mutex_init(&the_mutex,0);pthread_mutex_init(&the_main,0);pthread_cond_init(&condc,0);pthread_cond_init(&condp,0);pthread_mutex_lock(&the_main);for(j=1;j<=10;j=j+2){pthread_create(&pro[j],0,producer1,(void*)j);pthread_create(&con[j],0,consumer1,(void*)j);}printf("线程创建完成\n");pthread_mutex_unlock(&the_main);for(j=1;j<=30;j++){pthread_join(con[j],0);}printf("消费者线程结束\n");pthread_mutex_destroy(&the_main);pthread_cond_destroy(&condc);pthread_cond_destroy(&condp);pthread_mutex_destroy(&the_mutex);。
linux生产消费者模型的c语言实现概述及解释说明1. 引言1.1 概述本篇文章旨在介绍Linux生产者-消费者模型的C语言实现,并对其进行解释说明。
生产者-消费者模型是一种常见的多线程编程模型,用于处理共享数据的并发访问。
该模型通过将任务分为生产者和消费者两类角色来协调线程之间的工作,提高系统的性能和效率。
1.2 文章结构本文将按照以下顺序来讲解Linux生产者-消费者模型的C语言实现:- 引言:介绍本文的目的、内容和结构。
- 生产者-消费者模型:详细解释什么是生产者-消费者模型以及在Linux中的应用场景。
同时探讨该模型的优势和局限性。
- C语言实现生产者-消费者模型:介绍使用互斥锁和条件变量进行线程同步的方法,并讨论线程创建与销毁过程中需要注意的事项。
此外,还会涉及队列数据结构设计与实现方法。
- 示例代码演示与解读说明:展示完整示例代码,并逐行对其进行详细解读说明。
同时介绍如何运行结果分析以及问题排查技巧。
- 结论与展望:总结文章主要研究成果,探讨生产者-消费者模型的发展趋势和可能的改进方向,并对整篇文章进行总结。
1.3 目的本文旨在帮助读者理解Linux生产者-消费者模型的基本概念和原理,并提供具体实现方法。
通过示例代码的演示和解析,读者将能够掌握线程同步机制、队列数据结构以及运行结果分析等相关技术。
同时,为了深入了解该模型在实际应用中可能遇到的问题,本文还会介绍一些问题排查技巧。
通过阅读本文,读者将能够更好地应用生产者-消费者模型来优化自己的程序设计和开发工作。
2. 生产者-消费者模型:2.1 什么是生产者-消费者模型:生产者-消费者模型是一种常见的并发编程模式,用于解决多线程环境下的生产者和消费者之间的数据共享与同步问题。
在该模型中,生产者负责生成数据并将其放入共享区域,而消费者则从共享区域中获取数据进行处理。
通过这种方式,可以实现不同线程之间的解耦和协作。
2.2 在Linux中的应用场景:在Linux操作系统中,生产者-消费者模型得到广泛应用。