生产者消费者模型/条件变量

生产者消费者模型(简略)

//效率不高,引入条件变量
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

// 创建一个互斥量
pthread_mutex_t mutex;


struct  Node
{
    int num;
    struct Node * next;
};
struct Node * head = NULL;


void* producer(void * arg)
{
    //不断创造新的节点
    while(1){
    pthread_mutex_lock(&mutex);
    struct Node* newNode = (struct Node *)malloc(sizeof(struct Node));
    newNode->next = head;
    head = newNode;
    newNode->num = rand()%1000;
    printf("add node ,num :%d, tid : %ld\n",newNode->num,pthread_self());
    pthread_mutex_unlock(&mutex);
    usleep(100);
    }
    return NULL;
}
void * customer(void * arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        //保存头结点的指针
        struct Node * tmp =head;
        if(head != NULL)
        {
            //有数据
        head = head ->next;
        printf("del node num : %d, tid : %ld\n",tmp->num,pthread_self());
        free(tmp);
        pthread_mutex_lock(&mutex);
        usleep(100);
        }else
        {
            pthread_mutex_unlock(&mutex);
        }
    }
    return NULL;
}
int main()
{

    pthread_mutex_init(&mutex,NULL);
    //创建5个生产者线程,5个消费者线程
    pthread_t ptids[5],ctids[5];

    for(int i =0;i<5;i++)
    {
        pthread_create(&ptids[i],NULL,producer,NULL);
        pthread_create(&ctids[i],NULL,customer,NULL);
    }
    for(int i =0;i<5;i++)
    {
        pthread_detach(ptids[i]);
        pthread_detach(ctids[i]);
    }
    while(1)
    {
        sleep(10);
    }

    pthread_exit(NULL);
    pthread_mutex_destroy(&mutex);

    return 0;
}

条件变量

查询法改通知法,通知机制

产生错误后查看错误,可生成core文件

ulimit -c unlimited

gdb prodcust 查看错误

 

条件变量辅助互斥量完成线程同步

◼	条件变量的类型 pthread_cond_t
◼	int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
◼	int pthread_cond_destroy(pthread_cond_t *cond);
◼	int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//发现条件不成立,就解锁等待(先解锁,等待signal或broadcast,临界区外等待),等到断开wait
//wait放到循环中(	
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);//超时设置,在等待这么长时间之内还没有发生目标,就结束
◼	int pthread_cond_signal(pthread_cond_t *cond);  //通知某一个线程,叫醒哪个不知道
◼	int pthread_cond_broadcast(pthread_cond_t *cond);//以广播的方式通知全部等待目标条件变量的线程
//加条件变量的生产者消费者模型
/*
    条件变量的类型 pthread_cond_t
    int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
    int pthread_cond_destroy(pthread_cond_t *cond);
    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
        - 等待,调用了该函数,线程会阻塞。
    int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
        - 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束。
    int pthread_cond_signal(pthread_cond_t *cond);
        - 唤醒一个或者多个等待的线程
    int pthread_cond_broadcast(pthread_cond_t *cond);
        - 唤醒所有的等待的线程
*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

// 创建一个互斥量
pthread_mutex_t mutex;
// 创建条件变量
pthread_cond_t cond;

struct Node{
    int num;
    struct Node *next;
};

// 头结点
struct Node * head = NULL;

void * producer(void * arg) {

    // 不断的创建新的节点,添加到链表中
    while(1) {
        pthread_mutex_lock(&mutex);
        struct Node * newNode = (struct Node *)malloc(sizeof(struct Node));
        newNode->next = head;
        head = newNode;
        newNode->num = rand() % 1000;
        printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
        
        // 只要生产了一个,就通知消费者消费
        pthread_cond_signal(&cond);

        pthread_mutex_unlock(&mutex);
        usleep(100);
    }

    return NULL;
}

void * customer(void * arg) {

    while(1) {
        pthread_mutex_lock(&mutex);
        // 保存头结点的指针
        struct Node * tmp = head;
        // 判断是否有数据
        if(head != NULL) {
            // 有数据
            head = head->next;
            printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
            free(tmp);
            pthread_mutex_unlock(&mutex);
            usleep(100);
        } else {
            // 没有数据,需要等待
            // 当这个函数调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的,继续向下执行,会重新加锁。
            pthread_cond_wait(&cond, &mutex);
            pthread_mutex_unlock(&mutex);
        }
    }
    return  NULL;
}

int main() {

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    // 创建5个生产者线程,和5个消费者线程
    pthread_t ptids[5], ctids[5];

    for(int i = 0; i < 5; i++) {
        pthread_create(&ptids[i], NULL, producer, NULL);
        pthread_create(&ctids[i], NULL, customer, NULL);
    }

    for(int i = 0; i < 5; i++) {
        pthread_detach(ptids[i]);
        pthread_detach(ctids[i]);
    }

    while(1) {
        sleep(10);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    pthread_exit(NULL);

    return 0;
}

 

posted @ 2021-09-28 22:00  wsq1219  阅读(59)  评论(0编辑  收藏  举报