1.前言
在Linux线程中,互斥锁只能让一个线程进入到临界区,而信号量运行多个线程同时进入临界区
2.信号量的实质
信号量实际是一个等待队列的计数器,也属于一种临界资源,获取信号量资源,会对信号量进行-1操作,释放信号量资源会对信号量资源进行+1操作。
注:信号量操作是原子操作
来源:https://blog.csdn.net/Code_ZX/article/details/85008036
3.信号量实现同步
3.1 原理
进程获取信号量资源前需要获取信号量资源,
若无信号量资源则阻塞等待
若有信号量资源,则对信号量进行p(-1)操作,在获取临界资源
当临界资源+1时,对应的信号量资源则执行V(+1)操作,然后唤醒在等待队列中等待获取临界资源的进程。
来源:https://blog.csdn.net/Code_ZX/article/details/85008036
3.2 主要用到的函数
头文件:#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem:需要初始化的信号量
pshared:信号量用于进程间共享还是线程间共享,0表示线程间共享
value:信号量的初始值
int sem_wait(sem_t *sem);
等待信号量,如果信号量大于0,将信号量减1并返回
如果信号量的值大于1,则线程阻塞,相当于P操作
成功:返回0
失败:返回-1
int sem_post(sem_t *sem);
释放信号量,让信号量的值加1,相当于v操作
并唤醒阻塞线程
int sem_destroy(sem_t *sem);
摧毁信号量,使用了sem_init的信号量才可以进行destroy操作
4.代码示例
/************************************************
头文件
************************************************/
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/************************************************
结构与变量
************************************************/
#define CAR_NUM 10
/*定义为全局变量,方便多个线程共享*/
sem_t gt_sem;
/************************************************
函数
************************************************/
/************************************************
* @brief 线程处理函数
* @param thread_id[IN] 线程ID
*************************************************/
void* get_service(void *thread_id)
{
int mi_car_parker_id = *((int*)(thread_id));
//对信号量进行-1操作
if(sem_wait(>_sem) == 0)
{
usleep(50);
printf("ui_car_parker %d get service\n",mi_car_parker_id);
sem_post(>_sem);//释放信号量,对信号量进行+1操作
}
}
int main()
{
/* 1.初始化信号量,初始值为1,表示一次只能进去一辆车
* 2.0表示线程间共享
*/
sem_init(>_sem,0,1);
//为每一个停车人创建一个线程ID
pthread_t ui_car_parker[CAR_NUM];
int i,i_thread_ret;
int i_car_parker_id;
for(i = 0;i < CAR_NUM;i++)
{
i_car_parker_id = i;
i_thread_ret = pthread_create(&ui_car_parker[i],NULL,get_service,&i_car_parker_id);
if(i_thread_ret != 0 )
{
perror("pthread_create error");
exit(1);
}else
{
printf("ui_car_parker %d arrvied\n",i);
}
usleep(5);
}
int j;
for(j = 0; j < CAR_NUM; j++)
{
pthread_join(ui_car_parker[j],NULL);
}
sem_destroy(>_sem);
return 0;
}
编译:
sudo gcc sem_test.c -o sem_test -lpthread
运行结果:
ui_car_parker 0 arrvied
ui_car_parker 0 get service
ui_car_parker 1 arrvied
ui_car_parker 1 get service
ui_car_parker 2 arrvied
ui_car_parker 2 get service
ui_car_parker 3 arrvied
ui_car_parker 4 arrvied
ui_car_parker 3 get service
ui_car_parker 5 arrvied
ui_car_parker 4 get service
ui_car_parker 5 get service
ui_car_parker 6 arrvied
ui_car_parker 6 get service
ui_car_parker 7 arrvied
ui_car_parker 7 get service
ui_car_parker 8 arrvied
ui_car_parker 8 get service
ui_car_parker 9 arrvied
ui_car_parker 9 get service
参考:
https://www.cnblogs.com/jiqingwu/p/linux_semaphore_example.html
https://blog.csdn.net/Code_ZX/article/details/85008036