Linux--多线程(二)

发布时间:2026/7/30 2:49:40
Linux--多线程(二) 文章目录Linux线程同步条件变量同步概念与竞态条件条件变量函数初始化销毁等待条件满足唤醒等待简单案例条件变量使用规范生产者消费者模型基于BlockingQueue的生产者消费者模型Linux线程同步条件变量当一个线程互斥地访问某个变量时它可能发现在其他线程改变状态之前它什么也做不了例如一个线程访问队列时发现队列为空它只能等待直到其他线程将一个节点添加到队列中。这种情况需要用到条件变量同步概念与竞态条件同步在保证数据安全的前提下让线程能够按照某种特定的顺序访问临界资源从而有效避免饥饿问题叫做同步竞态条件因为时序问题而导致程序异常我们称之为竞态条件。条件变量函数初始化intpthread_cond_init(pthread_cond_t*restrict cond,constpthread_condattr_t*restrict attr);参数 cond:要初始化的条件变量 attr:NULL销毁intpthread_cond_destroy(pthread_cond_t*cond);等待条件满足intpthread_cond_wait(pthread_cond_t*restrict cond,pthread_mutex_t*restrict mutex);参数 cond要在这个条件变量上等待 mutex互斥量唤醒等待// 唤醒在条件变量下等待的所有线程intpthread_cond_broadcast(pthread_cond_t*cond);// 唤醒在条件变量下等待队列的第一个线程intpthread_cond_signal(pthread_cond_t*cond);简单案例// 线程等待#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includepthread.h// 定义条件变量与互斥量pthread_cond_tcond;pthread_mutex_tmutex;// 定义线程的回调函数void*handle1(void*arg){while(1){// 等待条件满足pthread_cond_wait(cond,mutex);printf(活动\n);}}void*handle2(void*arg){while(1){// 唤醒等待pthread_cond_signal(cond);sleep(1);}}intmain(){pthread_tt1,t2;// 初始化条件变量pthread_cond_init(cond,NULL);// 初始化互斥量pthread_mutex_init(mutex,NULL);pthread_create(t1,NULL,handle1,NULL);pthread_create(t2,NULL,handle2,NULL);pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_cond_destroy(cond);pthread_mutex_destroy(mutex);return0;}程序执行的结果就是每个1秒就打印一次那么可能有同学会问为什么pthread_cond_wait需要互斥量呢条件等待是线程间同步的一种手段如果只有一个线程条件不满足一直等下去都不会满足所以必须要有一个线程通过某些操作改变共享变量使原先不满足的条件变得满足并且友好的通知等待在条件变量上的线程条件不会无缘无故的突然变得满足了必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据。// 错误的设计pthread_mutex_lock(mutex);while(condition_is_false){pthread_mutex_unlock(mutex);// 解锁之后等待之前条件可能已经满足信号已经发出但是该信号可能被错过pthread_cond_wait(cond);pthread_mutex_lock(mutex);}pthread_mutex_unlock(mutex);由于解锁和等待不是原子操作。调用解锁之后pthread_cond_wait之前如果已经有其他线程获取到互斥量并且条件满足发送了信号那么pthread_cond_wait将错过这个信号可能会导致线程永远阻塞在这个pthread_cond_wait。所以解锁和等待必须是一个原子操作。int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)进入该函数后会去看条件量等于0不等于就把互斥量变成1直到cond_wait返回把条件变量改成1把互斥量恢复成原样条件变量使用规范等待条件代码pthread_mutex_lock(mutex);while(条件为假){pthread_cond_wait(cond,mutex);}修改条件pthread_mutex_unlock(mutex);条件发送信号代码pthread_mutex_lock(mutex);// 设置条件为真pthread_cond_signal(cond);pthread_mutex_unlock(mutex);生产者消费者模型生产者消费者模式就是通过一个容器来解决生产者和消费之的强耦合问题。生产者和消费者彼此之间不直接通讯而通过阻塞队列来进行通讯所以生产者产完数据之后就不用等待消费者处理直接扔给阻塞队列消费者不找生产者要数据二十直接从阻塞队列里取阻塞队列就相当于一个缓冲区平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。基于BlockingQueue的生产者消费者模型在多线程编程中**阻塞队列(Blocking Queue)**是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区别在于当队列为空时从队列获取元素的操作将会被阻塞直到队列中被放入了元素当队列满时往队列里放元素的操作也会被阻塞直到有元素被从队列中取出以上操作都是基于不同的线程来说的线程在对阻塞队列进程操作时会被阻塞通的队列区别在于当队列为空时从队列获取元素的操作将会被阻塞直到队列中被放入了元素当队列满时往队列里放元素的操作也会被阻塞直到有元素被从队列中取出以上操作都是基于不同的线程来说的线程在对阻塞队列进程操作时会被阻塞[外链图片转存中…(img-cx8WHt0e-1785332983262)]