Linux应用编程:线程中的信号量同步

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(&gt_sem) == 0)
	{
		usleep(50);
		printf("ui_car_parker %d get service\n",mi_car_parker_id);
		sem_post(&gt_sem);//释放信号量,对信号量进行+1操作
	}
}

int main()
{
	
	/* 1.初始化信号量,初始值为1,表示一次只能进去一辆车
	 * 2.0表示线程间共享
	 */
	sem_init(&gt_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(&gt_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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值