消费者生产者问题---线程互斥锁+条件变量

来源:互联网 发布:烟台seo整站优化方案 编辑:程序博客网 时间:2024/04/24 20:47

想实现线程的同步,解决消费者问题,利用互斥锁,发现不能成功,也许还要加其他的只是,

#include <stdio.h>#include<pthread.h>#include<stdio.h>#include<unistd.h>#include<string.h>typedef struct{    int product[5];    int count;}PRODUCT;PRODUCT buffer;//缓冲区结构,消费者和生产者共同操作pthread_mutex_t mutex;//创建互斥锁pthread_t tid;//新线程号pthread_t tid_m;//主线程号void consumer()//消费者函数{   // while(1) //担心这个函数执行完了线程退出考虑加while(1)死循环,想在主函数用return终止这个线程,但是加上后只能写一次,读一次然后程序就不动了
//不加会先写一次,读一次,再写入两次。    {        pthread_mutex_lock(&mutex);//上锁        int i=buffer.count;        for(;buffer.count>0;buffer.count--)        {            printf("read %d is %d\n",buffer.count,buffer.product[i-buffer.count]);        }        pthread_mutex_unlock(&mutex);//解锁        pthread_join(tid_m,NULL);//等待生产者线程输入数据完毕   问题在这里 需要新的知识解决    }}void product(){    pthread_mutex_lock(&mutex);//上锁    for(buffer.count=0;buffer.count<5;buffer.count++)    {         sleep((unsigned)rand()%3);//线程休眠        buffer.product[buffer.count]=rand()%10;        printf("write %d is %d   \n",buffer.count,buffer.product[buffer.count]);    }    pthread_mutex_unlock(&mutex);//解锁    pthread_join(tid,NULL);//等待消费者线程 写数据完毕}int main(){    int ret,i;    tid_m=pthread_self();//获取主线程的id    time_t t;    srand((unsigned)time(&t));//随机数模仿速度不固定    memset(&buffer,0,sizeof(PRODUCT));//先清空缓冲区    pthread_mutex_init(&mutex,NULL);//初始化互斥锁    ret=pthread_create(&tid,NULL,(void*)consumer,NULL);//创建新线程    if(ret!=0)    {        perror("ret");        exit(0);    }    for(i=0;i<3;i++)//写三次    {       product();    }    pthread_mutex_unlock(&mutex);//销毁互斥锁    return 0;}

程序写入一次的时候,没有问题,但是写入三次的时候要么阻塞,要么不读去以后的写入,这里只是看到了互斥锁的特点,但是没有解决最终问题。还需要条件变量的知识。下面是修正后的程序,用到了条件变量,这个变量是用来对线程进行阻塞的。

#include <stdio.h>#include<pthread.h>#include<stdio.h>#include<unistd.h>#include<string.h>#define WRITE_TIMES 3 //生产次数typedef struct{    int product[5];    int count;}PRODUCT;PRODUCT buffer;//缓冲区结构,消费者和生产者共同操作pthread_mutex_t mutex;//创建互斥锁pthread_cond_t cond;//创建条件变量pthread_t tid;//新线程号pthread_t tid_m;//主线程号void consumer()//消费者函数{    static int T=0;    int i=0;    while(T<WRITE_TIMES)    {        pthread_mutex_lock(&mutex);//上锁        while(buffer.count!=5)        {   //当初不知道pthread_cond_wait函数加在哪里,忽视了线程共享同一进程的资源。            pthread_cond_wait(&cond,&mutex);//等待信号        }        i=buffer.count;        for(;buffer.count>0;buffer.count--)        {            printf("read %d is %d\n",buffer.count,buffer.product[i-buffer.count]);        }        pthread_mutex_unlock(&mutex);//解锁        T++;     }}void product(){    pthread_mutex_lock(&mutex);//上锁    for(buffer.count=0;buffer.count<5;buffer.count++)    {       // sleep((unsigned)rand()%2);//线程休眠,这里是模仿速度不固定,验证互斥锁是否其作用        buffer.product[buffer.count]=rand()%10;        printf("write %d is %d   \n",buffer.count,buffer.product[buffer.count]);    }    pthread_cond_signal(&cond);//接触消费者线程的锁定状态    pthread_mutex_unlock(&mutex);//解锁    sleep(1);//必须有,否则CPU执行速度太快,生产者线程来不及切换,导致生产WRITE_MAX次,只消费一次}int main(){    int ret,i;    tid_m=pthread_self();//获取主线程的id    time_t t;    srand((unsigned)time(&t));//随机数模仿速度不固定    memset(&buffer,0,sizeof(PRODUCT));//先清空缓冲区    pthread_mutex_init(&mutex,NULL);//初始化互斥锁    pthread_cond_init(&cond,NULL);//初始化条件变量    ret=pthread_create(&tid,NULL,(void*)consumer,NULL);//创建新线程    if(ret!=0)    {        printf("create thread fail \n");        exit(0);    }    for(i=0;i<WRITE_TIMES;i++)//生产WRITE——TIMES次    {       product();    }    pthread_join(tid,NULL);//等待消费者线程退出,生产者线程就是主线程,最后return退出    pthread_mutex_unlock(&mutex);//销毁互斥锁    pthread_cond_destroy(&cond);    return 0;}

现在思考下第一次为什么失败,当初理解有误,pthread_join函数是等待线程退出,类似与进程里面的wait_pid函数,而我理解成了阻塞当前线程,是不对的,首先我在product里面,最后等待新的线程执行完,然后新的线程开始执行,但是新的线程执行了后,我又调用pthread_join等待主线程结束,我当时认为这是只是阻塞线程,CPU会进行调度的,其实这两个线程你等着我死,我等着你死,然后就出现了程序不继续运行的情况了。

下面才是正确的执行情况,写三次,读取三次。





0 0