资讯中心

pthread 汇总

📅 2026/8/18 18:40:56
pthread 汇总
非阻塞定时器通过信号量SIGUSR1和定时器实现1s的Linux posix定时器。#include stdio.h #include signal.h #include pthread.h #include unistd.h #include time.h #include sys/time.h timer_t timerid; // 全局定时器ID void* timer_thread(void* arg) { sigset_t set; /* 信号掩码集合 */ int sig; /* 接收的信号值 */ /* 初始化信号集 */ sigemptyset(set); sigaddset(set, SIGUSR1); /* 阻塞SIGUSR1信号确保同步处理 */ pthread_sigmask(SIG_BLOCK, set, NULL); /* 信号处理主循环 */ while (1) { if (sigwait(set, sig) 0 sig SIGUSR1) { printf([%ld] Timer task executed\n, time(NULL)); } } return NULL; } int main() { pthread_t tid; /* 定时器事件配置 */ struct sigevent sev { .sigev_notify SIGEV_SIGNAL, /* 信号通知方式 */ .sigev_signo SIGUSR1 /* 使用SIGUSR1信号 */ }; /* 定时器间隔设置(1秒周期) */ struct itimerspec its { .it_value {.tv_sec 1, .tv_nsec 0}, /* 首次触发延迟 */ .it_interval {.tv_sec 1, .tv_nsec 0} /* 周期间隔 */ }; /* 主线程信号屏蔽设置 */ sigset_t set; sigemptyset(set); sigaddset(set, SIGUSR1); pthread_sigmask(SIG_BLOCK, set, NULL); /* 创建单调时钟定时器 */ if (timer_create(CLOCK_MONOTONIC, sev, timerid) -1) { perror(timer_create failed); return -1; } /* 启动定时器 */ timer_settime(timerid, 0, its, NULL); /* 创建信号处理线程 */ if (pthread_create(tid, NULL, timer_thread, NULL) ! 0) { perror(pthread_create failed); return -1; } /* 主线程等待子线程结束 */ pthread_join(tid, NULL); /* 程序结束前清理定时器 */ timer_delete(timerid); return 0; }条件变量-阻塞唤醒1. 阻塞与非阻塞1.1 概念阻塞调用函数不立即返回线程挂起等待某个事件时间、数据、信号、条件变量等非阻塞调用无论有没有达到目标条件函数立刻返回不会挂起线程1.2 CPU占用误区 1“阻塞就一定会占 CPU”忙等待while (1);才占满 CPUsleep、cond_wait、read 阻塞、select 这种内核阻塞线程挂起无 CPU 消耗。2. 代码#include stdio.h #include stdlib.h #include pthread.h #include unistd.h // 互斥锁、条件变量动态初始化方式 pthread_mutex_t mutex; pthread_cond_t cond; // 共享条件 int ready 0; void *consumer_thread(void *arg) { pthread_mutex_lock(mutex); // while 避免虚假唤醒绝对不能用if while (ready 0) { printf(消费者条件不满足开始阻塞等待...\n); // 释放mutex阻塞被唤醒后重新持有锁 pthread_cond_wait(cond, mutex); } printf(消费者收到唤醒信号条件满足ready %d\n, ready); pthread_mutex_unlock(mutex); return NULL; } void *producer_thread(void *arg) { sleep(2); // 模拟耗时准备工作 pthread_mutex_lock(mutex); ready 1; printf(生产者条件已就绪发送唤醒信号\n); pthread_cond_signal(cond); // 唤醒一个等待线程 pthread_mutex_unlock(mutex); return NULL; } int main(void) { pthread_t tid_consumer, tid_producer; // 动态初始化 mutex condmutex_init cond_init if (pthread_mutex_init(mutex, NULL) ! 0) { perror(pthread_mutex_init fail); return -1; } if (pthread_cond_init(cond, NULL) ! 0) { perror(pthread_cond_init fail); pthread_mutex_destroy(mutex); return -1; } // 创建线程 pthread_create(tid_consumer, NULL, consumer_thread, NULL); pthread_create(tid_producer, NULL, producer_thread, NULL); // 等待线程结束 pthread_join(tid_consumer, NULL); pthread_join(tid_producer, NULL); // 销毁资源 pthread_mutex_destroy(mutex); pthread_cond_destroy(cond); printf(main: 程序退出\n); return 0; }1. while(ready 1){}防止虚假唤醒。操作系统允许无任何 signal 情况下线程从 cond_wait 苏醒这叫虚假唤醒 (spurious wakeup)。2./**消费者等待cond**/ pthread_mutex_lock(mutex); while (ready 0) { //释放锁 pthread_cond_wait(cond, mutex); //拿到锁 } pthread_mutex_unlock(mutex); /**生产者修改cond**/ pthread_mutex_lock(mutex); ready 1; pthread_cond_signal(cond); pthread_mutex_unlock(mutex);mutex主要为了保护ready公共态信号。如果没有mutex锁保护消费者线程如果判断ready0后还未到wait生产者把ready 1 修改并发送cond但是消费者线程为接收到则一直等待。如果有mutex保护消费者线程拿到锁ready0wait后释放锁生产者拿到锁修改ready状态发送信号量释放锁消费者拿到cond拿到锁释放锁。