美文网首页
条件变量

条件变量

作者: 写一行代码 | 来源:发表于2020-08-26 22:52 被阅读0次

    头文件:#include <pthread.h>

    与互斥锁不同,条件变量是用来等待而不是用来上锁的,条件变量本身不是锁!
    条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。
    条件变量的两个动作:
    条件不满, 阻塞线程
    当条件满足, 通知阻塞的线程开始工作

    pthread_cond_init

    int pthread_cond_init(pthread_cond_t *restrict cond,
    const pthread_condattr_t *restrict attr);
    功能:
    初始化一个条件变量
    参数:
    cond:指向要初始化的条件变量指针。
    attr:条件变量属性,通常为默认值,传NULL即可
    也可以使用静态初始化的方法,初始化条件变量:
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    返回值:
    成功:0
    失败:非0错误号

    pthread_cond_destroy

    int pthread_cond_destroy(pthread_cond_t *cond);
    功能:
    销毁一个条件变量
    参数:
    cond:指向要初始化的条件变量指针
    返回值:
    成功:0
    失败:非0错误号

    pthread_cond_wait

    int pthread_cond_wait(pthread_cond_t *restrict cond,
    pthread_mutex_t *restrict mutex);
    功能:
    阻塞等待一个条件变量
    a) 阻塞等待条件变量cond(参1)满足
    b) 释放已掌握的互斥锁(解锁互斥量)相当于pthread_mutex_unlock(&mutex);
    a) b) 两步为一个原子操作。
    c) 当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex);

    参数:
    cond:指向要初始化的条件变量指针
    mutex:互斥锁

    返回值:
    成功:0
    失败:非0错误号

    pthread_cond_timedwait

    int pthread_cond_timedwait(pthread_cond_t *restrict cond,
    pthread_mutex_t *restrict mutex,
    const struct timespec *restrict abstime);
    功能:
    限时等待一个条件变量

    参数:
    cond:指向要初始化的条件变量指针
    mutex:互斥锁
    abstime:绝对时间

    返回值:
    成功:0
    失败:非0错误号

    abstime说明:

    struct timespec {
    time_t tv_sec; /* seconds / // 秒
    long tv_nsec; /
    nanosecondes*/ // 纳秒
    }
    time_t cur = time(NULL); //获取当前时间。
    struct timespec t; //定义timespec 结构体变量t
    t.tv_sec = cur + 1; // 定时1秒
    pthread_cond_timedwait(&cond, &t);

    pthread_cond_signal

    int pthread_cond_signal(pthread_cond_t *cond);
    功能:
    唤醒至少一个阻塞在条件变量上的线程
    参数:
    cond:指向要初始化的条件变量指针
    返回值:
    成功:0
    失败:非0错误号

    pthread_cond_broadcast

    int pthread_cond_broadcast(pthread_cond_t *cond);
    功能:
    唤醒全部阻塞在条件变量上的线程
    参数:
    cond:指向要初始化的条件变量指针
    返回值:
    成功:0
    失败:非0错误号

    生产者消费者程序

    typedef struct node
    {
        int data;
        struct node* next;
    }Node;
    ​
    Node* head = NULL;
    ​
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    ​
    void* producer(void* arg)
    {
        while (1)
        {
            Node* pnew = (Node*)malloc(sizeof(Node));
            pnew->data = rand() % 1000; // 0-999
    
            pthread_mutex_lock(&mutex);
            pnew->next = head;
            head = pnew;
            printf("====== produce: %lu, %d\n", pthread_self(), pnew->data);
            pthread_mutex_unlock(&mutex);
            pthread_cond_signal(&cond);
    ​
            sleep(rand() % 3);
        }
        return NULL;
    }
    ​
    void* customer(void* arg)
    {
        while (1)
        {
            pthread_mutex_lock(&mutex);
            if (head == NULL)
            {
                // 该函数会对互斥锁解锁
                pthread_cond_wait(&cond, &mutex);
                // 解除阻塞之后,对互斥锁做加锁操作
            }
            // 链表不为空  - 删除头结点
            Node* pdel = head;
            head = head->next;
            printf("------ customer: %lu, %d\n", pthread_self(), pdel->data);
            free(pdel);
            pthread_mutex_unlock(&mutex);
        }
        return NULL;
    }
    ​
    int main(int argc, const char* argv[])
    {
        pthread_t p1, p2;
    
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond, NULL);
    ​
        pthread_create(&p1, NULL, producer, NULL);
        pthread_create(&p2, NULL, customer, NULL);
    ​
        pthread_join(p1, NULL);
        pthread_join(p2, NULL);
    ​
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
    ​
        return 0;
    }
    

    ​##条件变量的优缺点
    相较于mutex而言,条件变量可以减少竞争。
    如直接使用mutex,除了生产者、消费者之间要竞争互斥量以外,消费者之间也需要竞争互斥量,但如果链表中没有数据,消费者之间竞争互斥锁是无意义的。
    有了条件变量机制以后,只有生产者完成生产,才会引起消费者之间的竞争。提高了程序效率。

    相关文章

      网友评论

          本文标题:条件变量

          本文链接:https://www.haomeiwen.com/subject/epeojktx.html