条件变量pthread_cond_t +线程同步机制
1. 概念
- 条件变量是线程可用的另一种同步机制
- 条件变量给多个线程提供了一个会合的场所
- 条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生
- 条件变量是线程中的东西,就是等待某一条件的发生,和信号一样
2. 使用场景
- 条件变量要与互斥量一起使用,条件本身是由互斥量保护的。线程在改变条件状态之前必须首先锁住互斥量
- 其他线程在获得互斥量之前不会察觉到这种改变,因为互斥量必须在锁定以后才能计算条件
3. 数据类型
- pthread_cond_t
条件变量 同步程序运行的代码
deno1
#include <pthread.h> #include <stdio.h> #define MAX_BUF 5 int buf_cnt = 0; pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_full = PTHREAD_COND_INITIALIZER; pthread_cond_t cond_empty = PTHREAD_COND_INITIALIZER; // 生产者线程函数 void *producer(void *arg) { for (;;) { pthread_mutex_lock(&mtx); // 缓冲区满则等待 while (buf_cnt >= MAX_BUF) { pthread_cond_wait(&cond_full, &mtx); } buf_cnt++; printf("生产,当前数量:%d\n", buf_cnt); // 通知消费者有数据 pthread_cond_signal(&cond_empty); pthread_mutex_unlock(&mtx); } } // 消费者线程函数 void *consumer(void *arg) { for (;;) { pthread_mutex_lock(&mtx); // 缓冲区空则等待 while (buf_cnt <= 0) { pthread_cond_wait(&cond_empty, &mtx); } buf_cnt--; printf("消费,当前数量:%d\n", buf_cnt); // 通知生产者有空位 pthread_cond_signal(&cond_full); pthread_mutex_unlock(&mtx); } } // 【新增】C程序入口main函数 int main() { pthread_t prod_thread; // 生产者线程标识符 pthread_t cons_thread; // 消费者线程标识符 // 1. 创建生产者线程 pthread_create(&prod_thread, NULL, producer, NULL); // 2. 创建消费者线程 pthread_create(&cons_thread, NULL, consumer, NULL); // 3. 等待线程执行完毕(避免主线程提前退出) pthread_join(prod_thread, NULL); pthread_join(cons_thread, NULL); // 4. 销毁互斥锁和条件变量,释放系统资源 pthread_mutex_destroy(&mtx); pthread_cond_destroy(&cond_full); pthread_cond_destroy(&cond_empty); return 0; }
demo2
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <pthread.h> #include <unistd.h> #include <sys/prctl.h> // ==================== 共享状态与同步原语 ==================== static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static volatile bool data_available = false; // 数据就绪标志 static volatile bool should_exit = false; // 线程退出标志 // 模拟数据缓冲区 static int shared_data = 0; // ==================== 消费者线程 ==================== static void *FS_data_deal_thread(void *arg) { prctl(PR_SET_NAME, "FreeSerial"); while (1) { pthread_testcancel(); // 标准范式:在锁内检查条件,不满足则等待 pthread_mutex_lock(&mutex); while (!data_available && !should_exit) { pthread_cond_wait(&cond, &mutex); } // 被唤醒后,优先检查退出信号 if (should_exit) { pthread_mutex_unlock(&mutex); break; //----Main函数中将should_exit置1 逻辑到这里退出消费者的while循环,因此该线程处于退出状态,主函数没有自动退出的点 } // 消费数据 shared_data = 0; data_available = false; pthread_mutex_unlock(&mutex); // 模拟数据处理耗时 printf("[Consumer] Data processed successfully.\n"); } printf("[Consumer] Thread exiting gracefully.\n"); return NULL; } // ==================== 生产者线程 ==================== static void *FS_data_produce_thread(void *arg) { prctl(PR_SET_NAME, "FreeSerialProducer"); int count = 0; while (1) { pthread_testcancel(); // 模拟数据采集/生成过程 usleep(100000); // 100ms 生产间隔 count++; // 原子性地更新共享状态并发送通知 pthread_mutex_lock(&mutex); shared_data = count; data_available = true; pthread_cond_signal(&cond); // 精准唤醒消费者 pthread_mutex_unlock(&mutex); } return NULL; } // ==================== 主函数 ==================== int main(void) { pthread_t producer_tid, consumer_tid; printf("[Main] Starting producer-consumer threads...\n"); // 创建线程 if (pthread_create(&producer_tid, NULL, FS_data_produce_thread, NULL) != 0) { perror("Failed to create producer thread"); return EXIT_FAILURE; } if (pthread_create(&consumer_tid, NULL, FS_data_deal_thread, NULL) != 0) { perror("Failed to create consumer thread"); return EXIT_FAILURE; } // 模拟主线程运行一段时间 sleep(3); // ==================== 优雅退出 ==================== printf("[Main] Initiating graceful shutdown...\n"); pthread_mutex_lock(&mutex); should_exit = true; pthread_cond_signal(&cond); // 唤醒可能正在等待的消费者 pthread_mutex_unlock(&mutex); // 等待线程安全退出 pthread_join(producer_tid, NULL); pthread_join(consumer_tid, NULL); // 清理同步原语 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); printf("[Main] All threads joined. Program exiting.\n"); return EXIT_SUCCESS; }
浙公网安备 33010602011771号