多线程(11)多线程同步之信号量(Linux实现)
1. 什么是信号量?
信号量:用于多线程间的同步!
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。
2. 信号量使用方法
在进入一个关键代码段之前,线程必须获取一个信号量;
一旦该关键代码段完成了,那么该线程必须释放信号量。
其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。
3. 信号量的分类
在学习信号量之前,我们必须先知道——Linux提供两种信号量:
- 内核信号量,由内核控制路径使用
- 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEM V信号量。
POSIX信号量又分为有名信号量和无名信号量
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。
无名信号量,其值保存在内存中。
本博客主要是讲POSIX信号量的无名信号量
4. 信号量的工作原理
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),
他们的行为是这样的:
P(sv): 释放资源:如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行。
V(sv):申请资源:如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1。
5. 信号量(POSIX的无名信号量)有4种操作
-
初始化(initialize),也叫做建立(create)
int sem_init(sem_t *sem, int pshared, unsigned int value);
返回值:成功返回0,失败返回-1;
参数sem:表示指向信号结构的指针。
参数pshared:不是0 的时候该信号量在进程间共享,否则只能在当前进程的所有线程间共享。
参数value:信号量的初始值。 -
等信号(wait),也可叫做挂起(suspend),
信号量减一操作,有线程申请资源
int sem_wait(sem_t *sem); //相当于P操作,即申请资源。
成功返回0,否则返回-1
参数sem:指向一个信号量的指针 -
给信号(signal)或发信号(post)
信号量加一操作,有线程释放资源
int sem_post(sem_t *sem); //相当于V操作,释放资源。
成功返回0,否则返回-1
参数sem:指向一个信号量指针 -
清理(destroy)
int sem_destory(sem_t *sem);
6. 代码实现
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define MAXSIZE 10
int stack[MAXSIZE];
int size =0;
sem_t sem;
void privide_data(void)
{
int i;
for(i =0;i<MAXSIZE;++i)
{
stack[i] = i;
sem_post(&sem);
}
}
void handle_data(void)
{
int i;
while((i = size ++) <MAXSIZE)
{
sem_wait(&sem);
printf("cross : %d X %d = %d \n",stack[i],stack[i],stack[i] * stack[i]);
sleep(1);
}
}
int main()
{
pthread_t privider,handler;
sem_init(&sem,0,0);
pthread_create(&privider,NULL,(void *)&privide_data,NULL);
pthread_create(&handler,NULL,(void *)&handle_data,NULL);
pthread_join(privider,NULL);
pthread_join(handler,NULL);
sem_destroy(&sem);
return 0;
}
参考
https://blog.csdn.net/wangcg123/article/details/79666424
https://blog.csdn.net/qq_41248872/article/details/82991949