信号量
-
引用
#include <semaphore.h> -
全局声明
static sem_t sem -
初始化信号量
int sem_init(sem_t* sem, int pshared, unsigned int value);- sem 将要保存信号量的变量地址值
- pshared 决定由几个进程共享
- 传递0时,只允许1个进程内部使用
- value 新创建的信号量的初始值
-
请求信号量(减1)
int sem_wait(sem_t* sem);- 进入临界区前调用
- 调用后,如果信号量为0,则进入阻塞状态,否则减1后返回
-
归还信号量(加1)
int sem_post(sem_t* sem);- 离开临界区后调用
- 调用后,加1返回,如果此时有阻塞的线程,则可以重新减回0并跳出阻塞状态
-
销毁信号量
int sem_destroy(sem_t* sem); -
信号量的两种用途
-
同时访问互斥——只需1个互斥量
sem_wait(&sem); //临界区 sem_post(&sem); -
控制访问顺序——需要2个互斥量,一个为1,一个为0
#include <stdio.h> #include <pthread.h> #include <semaphore.h> void* read(void*arg); void* accu(void* arg); static sem_t sem_one; static sem_t sem_two; static int num; int main(int argc, char* argv[]) { pthread_t id_t1, id_t2; sem_init(&sem_one, 0, 0); sem_init(&sem_two, 0, 1); pthread_create(&id_t1, NULL, read, NULL); pthread_create(&id_t2, NULL, accu, NULL); pthread_join(id_t1, NULL); pthread_join(id_t2, NULL); sem_destroy(&sem_one); sem_destroy(&sem_two); return 0; } void* read(void*arg) { for (int i = 0; i < 5; i++) { puts("Input num: "); sem_wait(&sem_two); scanf("%d", &num); sem_post(&sem_one); } return NULL; } void* accu(void* arg) { int sum = 0; for (int i = 0; i < 5; i++) { sem_wait(&sem_one); sum += num; sem_post(&sem_two); } printf("Result: %d \n", sum); return NULL; }- 解释
- 初始 —— 1号信号量为0,2号信号量为1
- read函数先sem_wait请求2号信号量,然后等待输入,只有输入了才会sem_post归还1号互斥量,然后下一次循环堵住
- accu函数堵在sem_wait请求1号互斥量,只有read输入完,才会继续往下执行,追加到sum,并sem_post归还2号信号量,这样上面read的下一次循环才能开始
- 这样循环往复,就能实现两个函数按照“输入一次,追加一次”的顺序执行
- 编译时注意,要加上
-lpthreadgcc semaphore.c -o semaphore -lpthread- 要在Linux下才能成功
- 在macOS下会提示init和destroy函数是deperated
- 虽然能执行,但Result却是立刻输出了
- 输出——需要陆续输入数字,最后才会返回结果
Input num: 1 Input num: 2 Input num: 3 Input num: 4 Input num: 5 Result: 15
- 解释
-