线程同步之条件变量

linux下的条件变量

一、线程同步之条件变量

条件变量是用来等待线程而不是上锁的 ,条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用

条件变量是一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件。

当条件满足的时候,线程通常解锁并等待该条件发生变化,一旦另一个线程修改了环境变量,就会通知相应的环境变量唤醒一个或者多个被这个条件变量阻塞的线程。这些被唤醒的线程将重新上锁,并测试条件是否满足。一般来说条件变量被用于线程间的同步;当条件不满足的时候,允许其中的一个执行流挂起和等待。

二、条件变量函数

(1)条件变量的初始化

  • 静态:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;

    动态:通过调用pthread_cond_init函数,函数原型为: int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

    • cond:环境变量.
    • attr:条件变量属性.
    • 成功返回0,失败返回错误码.

    (2)条件变量摧毁函数:int pthread_cond_destroy(pthread_cond_t *cond);

    • 成功返回0,失败返回错误码.
    • 摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不等待在参数所指定的条件变量上。

    (3).条件变量等待函数

    • 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);

    • cond:条件变量
    • mutex:互斥锁

    pthread_cond_wait和pthread_cond_timedwait的区别:

    ​ pthread_cond_timedwait函数类型与函数pthread_cond_wait,区别在于,如果达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME.

    (4)条件变量通知函数

    • int pthread_cond_broadcast(pthread_cond_t *cond);
    • int pthread_cond_signal(pthread_cond_t *cond);

    pthread_cond_signal和pthread_cond_broadcast的区别:

    • pthread_cond_signal:只唤醒一个在相同条件变量中阻塞的线程将会被唤醒
    • pthread_cond_broadcast:唤醒等待队列中的所有线程

    三、代码

    
    
    #include<stdio.h>
    
    
    #include<stdlib.h>
    
    
    #include<assert.h>
    
    
    #include<pthread.h>
    
    
    typedef struct LinkNode
    {
    int data;
    struct LinkNode *next;
    }Node;
    
    pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t mycond=PTHREAD_COND_INITIALIZER;
    
    Node *CreatNode(int data)
    {
    Node *NewNode=(Node *)malloc(sizeof(Node));
    if(NULL == NewNode)
    {
        perror("malloc");
        return NULL;
    }
    NewNode->data=data;
    NewNode->next=NULL;
    return NewNode;
    }
    
    void InitLink(Node **head)
    {
    *head=CreatNode(0);
    }
    
    int IsEmpty(Node *head)
    {
    assert(head);
    if(head->next)
        return 0;    //not empty
    else
        return 1;    //empty
    }
    
    void PushFront(Node *head,int data)
    {
    assert(head);
    Node *NewNode=CreatNode(data);
    NewNode->next=head->next;
    head->next=NewNode;
    }
    
    void PopFront(Node *head,int *data)
    {
    assert(data);
    assert(head);
    if(IsEmpty(head))
    {
        printf("empty link\n");
        return ;
    }
    Node *del=head->next;
    *data=del->data;
    head->next=del->next;
    free(del);
    del=NULL;
    }
    
    void DisplayLink(Node *head)
    {
    assert(head);
    Node *cur=head->next;
    while(cur)
    {
        printf("%d ",cur->data);
        cur=cur->next;
    }
    printf("\n");
    }
    
    void DestroyLink(Node *head)
    {
    int data=0;
    assert(head);
    while(!IsEmpty(head))
    {
        PopFront(head,&data);
    }
    free(head);
    }
    
    void *product_run(void *arg)
    {
    int data=0;
    Node *head=(Node *)arg;
    while(1)
    {
        usleep(100000);
        data=rand()%1000;
        pthread_mutex_lock(&mylock);
        PushFront(head,data);
        pthread_mutex_unlock(&mylock);
        pthread_cond_signal(&mycond);
        printf("product is done,data=%d\n",data);
    }
    }
    
    void *consumer_run(void *arg)
    {
    int data=0;
    Node *head=(Node *)arg;
    while(1)
    {
        pthread_mutex_lock(&mylock);
        while(IsEmpty(head))
        {
            pthread_cond_wait(&mycond,&mylock);
        }
        PopFront(head,&data);
        pthread_mutex_unlock(&mylock);
        printf("consumer is done,data=%d\n",data);
    }
    }
    
    int main()
    {
    Node *head=NULL;
    InitLink(&head);
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL,product_run,(void *)head);
    pthread_create(&tid2,NULL,consumer_run,(void *)head);
    
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    DestroyLink(head);
    pthread_mutex_destroy(&mylock);
    pthread_cond_destroy(&mycond);
    return 0;
    
    }
    

    结果:

    wz@wz-machine:~/linux$ ./text3 
    product is done,data=383
    consumer is done,data=383
    consumer is done,data=886
    product is done,data=886
    consumer is done,data=777
    product is done,data=777
    consumer is done,data=915
    product is done,data=915
    

猜你喜欢

转载自blog.csdn.net/Travelerwz/article/details/81659952