阅读了《Unix/Linux系统编程》中关于Pthread信号量和屏障的内容,结合网上资料进行了整理
参考资料
6. 信号量
信号量是进程/线程同步的一种机制。它是一种特殊的变量,它可以被增加或减少,但对信号量的访问被保证是原子操作。
在POSIX
中,信号量是sem_t
类型。可以对信号量进行P/V
操作,POSIX中的信号量中有一个计数值,P操作对信号量-1,V操作对信号量+1。
需要inculude<semaphore.h>
6.1 信号量初始化
int sem_init(sem_t * sem, int pshared, unsigned int value)
- 参数
sem
:指向信号量变量的指针 pshared
:是否在多个进程中使用信号量(0线程同步;1进程同步)value
:初始计数值
6.2 信号量P/V操作
P操作:
对信号量进行P操作。当信号量值为0,线程阻塞等待V操作唤醒(线程被投入睡眠,等待该信号量值变为大于0,再将其减1并返回 );否则信号量值-1并返回。这里对信号量的-1是原子性的。
int sem_wait(sem_t * sem)
V操作:
对信号量进行V操作。信号量值+1,然后唤醒等待该信号量值变为正数的任意一个线程(注意如果有两个阻塞在该信号量P处的线程,那么该信号量的V操作只能唤醒其中一个阻塞的线程)。这里对信号量的+1是原子性的。
int sem_post(sem_t *__sem)
6.3 信号量解决生产者消费者问题:
定义一个int类型全局变量num,并指定其上限。创建10个生产者线程不停往里面+1直到加到上限,然后就不能加了,要等消费者减后才能继续加;创建10个消费者线程不停往里面-1直到减到0,然后就不能减了,要等生产者加后才能继续减。
注意在多线程问题中信号量往往要配合互斥量一起使用。因为如果多个线程P(sem)后同时操作全局共享变量,会由于同时访问导致出错(因为该访问全局共享资源的操作可能不是原子性的)。如下面的代码如果把互斥锁的上锁解锁语句注释掉,那么结果会出错(num的值会小于0或大于上限)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#define MAX 5//num范围为0-5
int num;//全局共享变量
sem_t* full;//信号量full,有多少个产品
sem_t* empty;//信号量empty,表示还能生产多少个产品就满了
pthread_mutex_t * m;
//消费者线程入口函数
void* consumer(void*arg){
for(int i = 0 ; i < 30 ;