Linux多线程12-生产者和消费者模型

发布时间 2023-06-26 09:04:05作者: 言叶以上

image

一个最简单的生产者消费者模型

/*
生产者消费者模型(粗略版)
*/

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

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

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


void* producer(void* arg){
    //往容器中添加内容
    //不断的创建新节点, 添加到链表中
    while(1){
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        newNode -> next = head;
        head = newNode;
        newNode -> num = rand()%1000;
        printf("add node, num: %d, tid: %d\n", newNode->num, pthread_self())''
        usleep(100);
    }
    return NULL;
}
void* customer(void* arg){
    //从容器中消费内容
    while(1){
        //保存头节点指针
        struct Node* tmp = head;
        head = head->next;
        printf("delete node, num: %d, tid: %ld\n", tmp->num, pthread_self());
        free(tmp);
        usleep(100);
    }
    return NULL;
}


int main(){
    //5个生产者线程, 5个消费者线程
    pthread_t ptid[5], ctid[5];

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

    for(i=0; i<5; i++){
        pthread_detach(ptid[i]);
        pthread_detach(ctid[i]);
    }

    // while(1){
    //     sleep(10);
    // }

    pthread_exit(NULL);

    return 0;
}

问题:

  1. Segmentation fault (core dumped) 段错误

    生成core文件

    $ ulimit -a
    core file size          (blocks, -c) 0
    $ ulimit -c unlimited
    $ ulimit -a
    core file size          (blocks, -c) unlimited
    $ gcc producer.c -o producer -g -pthread
    $ ./producer 
    Segmentation fault (core dumped)
    
  2. 查看错误

    (gdb) core-file core
    [New LWP 2112]
    [New LWP 2110]
    [New LWP 2115]
    [New LWP 2113]
    [New LWP 2111]
    [New LWP 2114]
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    Core was generated by `./producer'.
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0  0x0000000000400906 in customer (arg=0x0) at producer.c:37
    37              head = head->next;
    
  3. (如果head为空, 是无法访问head->next)

代码修改:

/*
生产者消费者模型(粗略版)
*/

#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("delete node, num: %d, tid: %ld\n", tmp->num, pthread_self());
            free(tmp);
            pthread_mutex_unlock(&mutex);
            usleep(100);
        }else{
            //没有数据就解锁,防止又回去重复加锁,导致死锁
            pthread_mutex_unlock(&mutex);
        }
    }
    return NULL;
}


int main(){
    pthread_mutex_init(&mutex, NULL);

    //5个生产者线程, 5个消费者线程
    pthread_t ptid[5], ctid[5];

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

    for(i=0; i<5; i++){
        pthread_detach(ptid[i]);
        pthread_detach(ctid[i]);
    }

    while(1){
        sleep(10);
    }

    pthread_mutex_destroy(&mutex);

    pthread_exit(NULL);

    return 0;
}