回顾 System V 信号量

还记得这张图不?这是当年在讲进程通信时候,通过讲述电影院的故事,画出的图。上一节我们又有了阻塞队列的知识储备。
阻塞队列当成整体使用,如果此时拆分成一个个小资源呢?让不同的线程访问同一块资源的不同部分,那么不就相当于允许多个线程并发访问同一块资源了吗?
整体使用就是要有互斥能力;
局部使用,访问错了,分多资源应该要规避
-
放过多线程进入,本质就是访问信号量,而信号量本质是一把计数器!(信号量就是一个计数器,可以理解为锁 + 整数) --> 那么该如何表示信号量还剩多少资源,资源被申请多少了呢?PV 操作
-
要申请信号量 --> 前提是看到同一个信号量 --> 信号量本身就要是共享资源 --> 如何保证自己的安全? --> PV 操作是原子性的
-
让不同的线程,访问同一块资源的不同部分,这个资源在哪里呢?需要让程序员做!
POSIX 信号量
POSIX 信号量和 SystemV 信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。但 POSIX 可以用于线程间同步。
认识信号量接口
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:初始化信号量
参数:
pshared:0 表示线程间共享,非零表示进程间共享 value:信号量初始值int sem_destroy(sem_t *sem);
功能:销毁信号量
int sem_wait(sem_t *sem); P 操作
功能:等待信号量,会将信号量的值减 1
int sem_post(sem_t *sem); V 操作
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加 1。
上一节生产者 - 消费者的例子是基于 queue 的,其空间可以动态分配,现在基于固定大小的环形队列重写这个程序(POSIX 信号量):
环形队列

单生产单消费场景
我们现在有信号量这个计数器,就很简单的进行多线程间的同步过程。

- 为空的时候,必须让生产者先运行 --> 生产和消费会访问同一个位置 --> 互斥放入数据 --> 这不就是生产和消费者的互斥与同步关系!
- 为满的时候,必须让消费者先运行 --> 生产和消费又指向同一个位置了! --> 互斥的获取数据 --> 这不就是生产和消费者的互斥与同步关系!
- 不为空 && 不为满:此时首 != 尾,访问的一定不是同一个位置! --> 此时,不就可以并发执行了?!





