1. 程式人生 > >linux程式設計---執行緒---條件變數

linux程式設計---執行緒---條件變數

條件變數通訊機制

基本原理

初始化條件變數
int pthread_cond_init(pthread_cond_t *restrict cond,
              const pthread_condattr_t *restrict attr);
              
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

銷燬條件變數
int pthread_cond_destroy(pthread_cond_t *cond);

通知等待條件變數的執行緒
用於喚醒等待出現與條件變數cond關聯的條件的所有執行緒
int pthread_cond_broadcast(pthread_cond_t *cond);
用於喚醒等待出現與條件變數cond關聯的條件的第一條執行緒
int pthread_cond_signal(pthread_cond_t *cond);

等待條件變數
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex,
              const struct timespec *restrict abstime);
              
int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
如果某執行緒因等待條件變數進入等待狀態時,將隱含釋放其申請的互斥鎖。
同樣,在返回時,首先要申請到該互斥鎖物件。
              
程式示例:
程式處理生產消費問題,整個臨時儲存空間為2,即在任意時刻,最多能夠有2個產品存放在臨時
空間,如果已經有2個產品存放在臨時空間,將阻塞生產執行緒。如果臨時空間中沒有產品,顯示
需要阻塞消費執行緒。程式主要實現了生產和消費兩個執行緒同步。

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

#define BUFSIZE 2

struct prodcons
{
    int buf[BUFSIZE];
    pthread_mutex_t lock;
    int readpos,writepos;
    pthread_cond_t notempty;
    pthread_cond_t notfull;
};

void init(struct prodcons *prod)
{
    pthread_mutex_init(&prod->lock,NULL);
    pthread_cond_init(&prod->notempty,NULL);
    pthread_cond_init(&prod->notfull,NULL);
    prod->readpos = 0;
    prod->writepos = 0;
}

void put(struct prodcons* prod,int data)
{
    pthread_mutex_lock(&prod->lock);
    while((prod->writepos+1) % BUFSIZE == prod->readpos)
    {
        printf("producer wait for not full\n");
        pthread_cond_wait(&prod->notfull,&prod->lock);
    }
    prod->buf[prod->writepos] = data;
    prod->writepos++;
    if(prod->writepos >= BUFSIZE)
            prod->writepos = 0;
    pthread_cond_signal(&prod->notempty);
    pthread_mutex_unlock(&prod->lock);
}

int get(struct prodcons* prod)
{
    int data;
    pthread_mutex_lock(&prod->lock);
    while(prod->writepos == prod->readpos)
    {
        printf("consumer wait for not empty\n");
        pthread_cond_wait(&prod->notempty,&prod->lock);
    }
    data = prod->buf[prod->readpos];
    prod->readpos++;
    if(prod->readpos >= BUFSIZE)
            prod->readpos = 0;
    pthread_cond_signal(&prod->notfull);
    pthread_mutex_unlock(&prod->lock);
    return data;
}

#define OVER (-1)
struct prodcons buf;

void* producer(void* data)
{
    int n;
    for(n=1;n <= 5;n++)
    {
        printf("producer sleep 1 second....\n");
        sleep(1);
        printf("put the %d producet\n",n);
        put(&buf,n);
    }
    for(n=6;n <= 10;n++)
    {
        printf("producer sleep 3 second....\n");
        sleep(3);
        printf("put the %d producet\n",n);
        put(&buf,n);
    }
    put(&buf,OVER);
    printf("producer stopped\n");
    return NULL;
}

void* consumer(void* data)
{
    int d =0;
    while(1)
    {
        printf("consumer sleep 2 second...\n");
        sleep(2);
        d = get(&buf);
        printf("get the %d product\n",d);
        if(d == OVER)
            break;
    }
    printf("consumer stopped\n");
    return NULL;
}

int main()
{
    pthread_t th1,th2;
    void* retval;
    init(&buf);
    pthread_create(&th1,NULL,producer,0);
    pthread_create(&th2,NULL,consumer,0);
    
    pthread_join(th1,&retval);
    pthread_join(th2,&retval);

    return 0;
}