线程同步与互斥和生产消费模型
目录
一. 线程互斥
1.1 互斥量mutex
互斥量接口介绍(需要自己了解)
二.线程同步
同步接口介绍(需要自己了解)
三.生产者和消费者模型
记忆模型
3.1 为什么需要生产者消费者模型?
3.2基于阻塞队列的生产者消费者模型 博客不写了
四.信号量(也是用于同步操作)
信号量接口(需要自己了解):
一. 线程互斥
互斥:任何时刻,互斥保证 有且只有一个 执行流(线程)进入临界区,访问临界资源,通常对临界资源起保护作用
补充其他背景知识:
临界资源:多线程执行流 共享的资源 就叫做临界资源
临界区:访问临界资源的共享代码,就叫做临界区
原子性(后面讨论如何实现)不会被任何调度机制打断的操作,该操作只有两态,完成和没运行。
1.1 互斥量mutex
为什么需要互斥!!!因为,多个线程并发的操作共享变量,会带来一些问题,比如 网络多个用户抢票问题等。不细说了,懂得自然懂。
互斥量接口介绍(需要自己了解)
1. 初始化互斥量接口:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER // 静态全局int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);//动态分配 attr:null
2. 销毁互斥量
int pthread_mutex_destroy(pthread_mutex_t *mutex);
3.加锁和解锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//返回值:成功返回0,失败返回错误号
这里应该加一个抢票的例子,但是我懒得写了...自己搜索了解...
注:RAII风格的互斥锁,C++11 也有,比如:
std::mutex mtx;
std::lock_guard<std::mutex>guard(mtx);
二.线程同步
同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步
背景:
-
条件变量(Condition Variable):就像一个“等待室” 和“广播喇叭”。
-
当线程发现条件不满足时(比如队列为空),它会释放锁并主动进入等待室睡觉,这样别的线程就能干活了。
-
当另一个线程让条件变得满足时(比如向队列添加了数据),它就用广播喇叭叫醒等待的线程。
-
2. 竞态条件:因为 时序问题,而导致程序异常,我们称之为竞态条件。
注: 互斥锁和条件变量两者一般必须配合使用
同步接口介绍(需要自己了解)
1.条件变量函数 初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t
*restrict attr);
销毁
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件满足
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict
mutex);
唤醒等待线程(全部和一个)
int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒所有
int pthread_cond_signal(pthread_cond_t *cond);//唤醒一个
三.生产者和消费者模型
记忆模型
三种关系:
1.生产者之间 互斥与竞争
2.消费者与消费者 互斥
3.生产者和消费者 互斥与同步
两个角色: 生产者和消费者(线程)
一个交易场所: 以特定结构构成的“内存”空间
321
如图:
3.1 为什么需要生产者消费者模型?
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
生产者消费者模型的优点:解耦,支持并发,支持忙闲不均。
3.2基于阻塞队列的生产者消费者模型 博客不写了
这个生产者-消费者的例子是基于queue的,其空间可以动态分配。
四.信号量(也是用于同步操作)
信号量其实是一个计数器,是对资源的预订机制。
如果我们要写一个基于固定大小的环形队列,就可以用(POSIX信号量)重写这个程序。
信号量接口(需要自己了解):
初始化信号量
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:pshared:0表⽰线程间共享,⾮零表⽰进程间共享value:信号量初始值
销毁信号量
int sem_destroy(sem_t *sem);
等待信号量
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);
发布信号量
功能:发布信号量,表⽰资源使⽤完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);