信号量
在Linux下,POSIX信号量是一种线程同步机制,用于控制多个线程之间的访问顺序。POSIX信号量可以用于实现线程之间的互斥或者同步。
在之前的阻塞队列生产者消费者模型中,阻塞队列是一个共享资源,不管是生产者还是消费者,任何时刻只允许一个线程访问共享资源,所以对阻塞队列进行了加锁保护,使阻塞队列成为为临界资源。在这里,是将整个共享资源(阻塞队列)当作一个整体使用的。
信号量使用思路:一个共享资源,不当作整体使用,将其划分为若干个小的共享资源,使得不同的执行流访问不同的小共享资源,本质上,当不同执行流访问不同的小共享资源时,不需要进行加锁保护,可以并发执行。而如果两个执行流访问到了同一个小的共享资源时,再进行互斥保护共享资源。
POSIX信号量提供了两种类型的信号量:二进制信号量和计数信号量。二进制信号量只有两个取值:0和1,它用于表示资源是否被占用。计数信号量可以有多个取值,它表示可用资源的数量。
二进制信号量可以充当互斥锁的作用。因为信号量的初始值为1,p相当于加锁,v相当于解锁。
计数信号量的值通常被称为“资源计数器”,它记录了当前可用的共享资源数量。当一个线程需要使用共享资源时,它会尝试获取计数信号量,如果当前可用资源数量大于0,则线程可以获取资源并将计数信号量的值减1。如果当前可用资源数量为0,则表示共享资源已被占用,线程需要等待直到有资源可用。
POSIX信号量接口
int sem_init(sem_t *sem, int pshared, unsigned int value); // 初始化
int sem_destroy(sem_t *sem); // 销毁
int sem_wait(sem_t *sem); // 申请信号量,P操作
int sem_post(sem_t *sem); // 释放信号量,V操作
因为信号量本质就是一个计数器,记录着当前的资源数目,其中初始化时的value值就表示初始时的资源数目。
在使用POSIX信号量时,线程可以通过调用sem_wait()函数来请求获取信号量,如果当前信号量的值大于0,则线程可以继续执行,同时信号量的值会减1;否则线程将被阻塞,等待信号量的值变为大于0。当线程释放资源时,可以通过调用sem_post()函数来释放信号量,使得其它线程可以获取资源。
基于环形队列的生产者消费者模型
1.缓冲区的改变
![](https://i-blog.csdnimg.cn/blog_migrate/362e90c0693eb7e8e5dc7a39042442f2.png)
基于环形队列的生产者消费者模型,对比之前的基于阻塞队列的生产者消费者模型,只是缓冲区的具体数据结构变了。两个角色:生产者,消费者。三种关系:生产者与生产者:互斥。消费者与消费者:互斥。生产者与消费者:互斥与同步。
如上图,环节队列是逻辑抽象结构,底层的物理结构是数组。要想达到环形队列的效果,只需在访问数组的最后一个元素的下一个元素时将下标 %= size即可。再者,环形队列有一个判空和判满的问题,因为这里的容量是有上限的,从数据结构的角度来说,一般会有一个start和end下标,当start == end时为空,而当数据为满时,不能也将start == end标定为满,因为这样空和满的判断条件就相同了。解决方法