Linux--条件变量

条件变量是用来等待而不是用来上锁的,条件变量本身不是锁条件变量和互斥锁同时使用

条件变量的两个动作: 条件不满, 阻塞线程 当条件满足, 通知阻塞的线程开始工作。

条件变量的类型: pthread_cond_t


1、条件变量初始化

#include<pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

使用静态初始化的方法,初始化条件变量:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

功能:
        初始化一个条件变量
参数:
        cond:指向要初始化的条件变量指针。attr:条件变量属性,通常为默认值,传NULL即可
返回值:
        成功:0
        失败:非0错误号

2、释放条件变量

#include<pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);

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

3、等待条件

#include<pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

功能:
        阻塞等待一个条件变量先解锁、等待条件满足、重新上锁(3步为原子操作)解阻塞
参数:
        cond:指向要初始化的条件变量指针
        mutex:互斥锁
返回值:
        成功:0
        失败:非0错误号

int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,
const struct *abstime);

功能:
        限时等待一个条件变量
参数:
        cond:指向要初始化的条件变量指针mutex:互斥锁
        abstime:绝对时间
返回值:
        成功:0
        失败:非0错误号

4、唤醒等待在条件变量上的线程

#include<pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);

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

int pthread_cond_broadcast(pthread_cond_t* cond);

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

示例代码 生产者消费者

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

void err_thread(int ret, char *str)
{    
        if (ret != 0)
        {
             fprintf(stderr, "%s:%s\n", str, strerror(ret));
             pthread_exit(NULL);
         }
}

struct msg {
     int num;
     struct msg *next;
};
struct msg *head;


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;      // 定义/初始化一个互斥量 pthread_cond_t has_data = PTHREAD_COND_INITIALIZER;      // 定义/初始化一个条件变量

void *produser(void *arg)
{
     while (1) {
         struct msg *mp = malloc(sizeof(struct msg));
         mp->num = rand() % 1000 + 1; // 模拟生产一个数据
         printf("--produce %d\n", mp->num);
         pthread_mutex_lock(&mutex); // 加锁 互斥量
         mp->next = head;                                    // 写公共区域
         head = mp;
         pthread_mutex_unlock(&mutex);                       // 解锁 互斥量
         pthread_cond_signal(&has_data);                     // 唤醒阻塞在条件变量 has_data上的线程.
         sleep(rand() % 3);
     }
     return NULL;
}
void *consumer(void *arg) {
     while (1) {
         struct msg *mp;
         pthread_mutex_lock(&mutex);                         // 加锁 互斥量
         while (head == NULL) {
             pthread_cond_wait(&has_data, &mutex);           // 阻塞等待条件变量, 解锁
         }// pthread_cond_wait 返回时, 重新加锁 mutex
         mp = head;
         head = mp->next;
         pthread_mutex_unlock(&mutex);                       // 解锁 互斥量
         printf("---------consumer id: %lu :%d\n", pthread_self(), mp->num);
         free(mp);
         sleep(rand()%3);
     }    
     return NULL;
}

int main(int argc, char *argv[]) {
     int ret;
     pthread_t pid, cid;
     srand(time(NULL));
     ret = pthread_create(&pid, NULL, produser, NULL);           // 生产者
     if (ret != 0)
          err_thread(ret, "pthread_create produser error");
     ret = pthread_create(&cid, NULL, consumer, NULL);           // 消费者
     if (ret != 0)
          err_thread(ret, "pthread_create consuer error");
     ret = pthread_create(&cid, NULL, consumer, NULL);           // 消费者
     if (ret != 0)
          err_thread(ret, "pthread_create consuer error");
     ret = pthread_create(&cid, NULL, consumer, NULL);           // 消费者
     if (ret != 0)
          err_thread(ret, "pthread_create consuer error");
     pthread_join(pid, NULL);
     pthread_join(cid, NULL);
     return 0;
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容