1. 程式人生 > 其它 >生產者消費者模型/條件變數

生產者消費者模型/條件變數

生產者消費者模型(簡略)

//效率不高,引入條件變數
#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);
◼	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;
}