linux——条件变量

张开发
2026/4/9 2:17:14 15 分钟阅读

分享文章

linux——条件变量
条件变量阻塞线程不是什么时候都能阻塞线程链表头节点 Node*head NULL; while(head NULL) { //我们想让代码在这个位置阻塞 //等待链表中有了节点之后再继续向下运行 //使用到了后面要讲的条件变量‐阻塞线程 } //链表不为空的处理代码 xxxx1.条件变量是锁吗不是锁但是条件变量能够阻塞线程使用条件变量互斥量互斥量保护一块共享数据条件变量引起阻塞生产者和消费者模型2.条件变量的两个动作条件不满足阻塞线程当条件满足通知阻塞的线程开始工作3.条件变量的类型pthread_cond_t cond ;conditon 条件4.主要函数①初始化一个条件变量pthread_cond_init(pthread_cond_t * restrict cond, const pthread_condattr_t * restrict attr );②销毁一个条件变量pthread_cond_destroy(pthread_cond_t * cond);③阻塞等待一个条件变量pthread_cond_wait( pthread_cond_t *restrict cond, pthread_mutex_t * restrict mutex )阻塞线程将已经上锁的mutex解锁该函数解除阻塞对互斥锁加锁④限时等待一个条件变量pthread_cond_timedwait( pthread_cond_t * restrict cond, pthread_mutex_t * restrict mutex, const struct timespec * restrict abstime )⑤唤醒至少一个阻塞在条件变量上的线程pthread_cond_signal(pthread_cond_t* cond);⑥唤醒全部阻塞在条件变量上的线程pthread_cond_broadcast(pthread_cond_t * cond)5、练习使用条件变量实现生产者消费者模型#includestdio.h #includepthread.h #includeunistd.h #includestdlib.h typedef struct node { int data; struct node* next; }Node; //create head node Node* head NULL; //create mutex pthread_mutex_t mutex; //create cond pthread_cond_t cond; void* produce(void* arg) { while(1) { //create node Node* pnew (Node*)malloc(sizeof(Node)); //init node pnew-data rand()%1000; //lock pthread_mutex_lock(mutex); pnew-next head; head pnew; printf(produce:%ld,%d\n,pthread_self(),pnew-data); //unlock pthread_mutex_unlock(mutex); pthread_cond_signal(cond); sleep(rand()%3); } return NULL; } void* customer(void* arg) { while(1) { //lock pthread_mutex_lock(mutex); if(head NULL) { //continue; pthread_cond_wait(cond,mutex); } //delete head node Node* pdel head; head head-next; printf(customer:%ld,%d\n,pthread_self(),pdel-data); free(pdel); //unlock pthread_mutex_unlock(mutex); } return NULL; } int main() { pthread_t p1,p2; pthread_mutex_init(mutex,NULL); pthread_cond_init(cond,NULL); pthread_create(p1,NULL,produce,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; }这是【多线程 互斥锁 条件变量 生产者消费者模型】最标准的代码生产者线程不断创建链表节点头插法加入链表。消费者线程不断从链表头删除节点。解决了 3 个问题多线程操作共享链表 → 加互斥锁保护链表空了消费者不浪费 CPU →条件变量等待生产者生产完通知消费者来取 →条件变量唤醒①链表结构体typedef struct node { int data; // 数据域 struct node* next; // 指针域指向下一个节点 }Node;作用定义一个“节点”小盒子②全局链表头共享资源Node* head NULL;所有线程共享必须加锁保护③互斥锁条件变量pthread_mutex_t mutex; // 互斥锁保证操作链表安全 pthread_cond_t cond; // 条件变量控制等待与唤醒1. 互斥锁 mutex保证同一时间只有一个线程操作链表防止数据错乱、程序崩溃2. 条件变量 cond当链表为空时消费者阻塞等待生产者生产后发送信号唤醒消费者避免消费者空循环浪费 CPU④生产者线程producevoid* produce(void* arg) { while(1) // 无限循环生产 { // 1. 创建新节点 Node* pnew (Node*)malloc(sizeof(Node)); pnew-data rand()%1000; // 随机数 0~999加锁操作共享资源前必须加锁pthread_mutex_lock(mutex);链表头插法pnew-next head; head pnew;解锁操作完必须解锁pthread_mutex_unlock(mutex);条件变量唤醒等待的消费者告诉消费者我生产好了快来消费pthread_cond_signal(cond);随机休息sleep(rand()%3); // 随机休息 } return NULL; }⑤消费者线程void* customer(void* arg) { while(1) // 无限循环消费 { // 加锁 pthread_mutex_lock(mutex);如果链表为空等待不浪费CPUif(head NULL) { pthread_cond_wait(cond,mutex); }pthread_cond_wait做了 3 件事阻塞等待直到被唤醒自动解锁mutex让生产者可以生产被唤醒后自动重新加锁→ 这是条件变量最核心的机制链表头删法Node* pdel head; head head-next; printf(customer:%ld,%d\n,pthread_self(),pdel-data); free(pdel); // 释放节点解锁pthread_mutex_unlock(mutex); } return NULL; }⑥main函数int main() { pthread_t p1,p2; // 初始化锁和条件变量 pthread_mutex_init(mutex,NULL); pthread_cond_init(cond,NULL); // 创建线程 pthread_create(p1,NULL,produce,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; }运行结果都是先生产再消费

更多文章