首页 > 其他分享 >多线程同步之信号量

多线程同步之信号量

时间:2022-11-07 19:04:26浏览次数:52  
标签:同步 函数 int 信号量 线程 sem 多线程 id


对于多线程程序来说,同步是指在一定的时间内只允许某一个线程访问某个资源 。 而在
此时间内,不允许其他的线程访问该资源。同步资源的方式:互斥锁、条件变量、读写锁、
信号量。
信号量和互斥锁的区别: 互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区
信号量。

一、基本原理
信号量和互斥锁的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区。
以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

二、API
1、创建信号量
int sem_init(sem_t *sem , int pshared , unsigned int value) ;

sem :指向信号量对象

pshared : 指明信号量的类型。不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享。
  value : 指定信号量值的大小

调用成功返回0
2、sem wait 函数 。
该函数用于以原子操作的方式将信号量的值减 1 。 原子操作就是 ,如果两个线程企图 同

时给一个信号量加 1 或减 l ,它们之间不会互相干扰 , 函数的原型如下:
int sem_wait(sem_t *sem);
调用成功返回0,调用成功返回-1
3、 sem_post 函数 。
该函数用于以原子操作的方式将信号量的值加 1 ,函数的原型如下:
int sem__post (sem_ t *sem);
调用成功返回0,调用成功返回-1
4、sem_destroy 函数
该函数用于对用完的信号量进行清理,函数的原型如下:
int sem_destroy ( sem_t *s em);
成功时返回 0 ,失败时返回- 1 。

#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define CUSTOMER_NUM 10
/* @Scene: 某行业营业厅同时只能服务两个顾客。
* 有多个顾客到来,每个顾客如果发现服务窗口已满,就等待,
* 如果有可用的服务窗口,就接受服务。 */
/* 将信号量定义为全局变量,方便多个线程共享 */
sem_t sem;
/* 每个线程要运行的例程 */
void * get_service(void *thread_id)
{
/* 注意:立即保存thread_id的值,因为thread_id是对主线程中循环变量i的引用,它可能马上被修改*/
int customer_id = *((int *)thread_id);
if(sem_wait(&sem) == 0)
{
usleep(100); /* service time: 100ms */
printf("customer %d receive service ...\n", customer_id);
sem_post(&sem);
}
pthread_exit((void*)0);
}

int main(int argc, char *argv[])
{
/*初始化信号量,初始值为2,表示有两个顾客可以同时接收服务 */
sem_init(&sem,0,2);

/*为每个顾客定义一个线程id*/
pthread_t customers[CUSTOMER_NUM];

int i, iRet;
/* 为每个顾客生成一个线程 */
for(i = 0; i < CUSTOMER_NUM; i++)
{
int customer_id = i;
iRet = pthread_create(&customers[i], NULL, get_service, &customer_id);
if(iRet){
perror("pthread_create");
return iRet;
}
else{
printf("Customer %d arrived.\n", i);
}
usleep(10);
}

/* 等待所有顾客的线程结束 */
/* 注意:这地方不能再用i做循环变量,因为可能线程中正在访问i的值 */

int j;
for(j = 0; j < CUSTOMER_NUM; j++)
{
pthread_join(customers[j], NULL);
}
/*销毁信号量*/
sem_destroy(&sem);
return 0;
}
//运行环境Ununtu
把文件命名为Thread.cpp
编译:g++ -o Thread Thread.cpp -lpthread
运行./Thread


标签:同步,函数,int,信号量,线程,sem,多线程,id
From: https://blog.51cto.com/u_11320078/5830864

相关文章

  • C# 多线程访问之 SemaphoreSlim(信号量)【C# 进阶】
    SemaphoreSlim是对可同时访问某一共享资源或资源池的线程数加以限制的Semaphore的轻量替代,也可在等待时间预计很短的情况下用于在单个进程内等待。由于SemaphoreSlim......
  • 用Rust实现一个多线程的web server
    在本文之前,我们用Rust实现一个单线程的webserver的例子,但是单线程的webserver不够高效,所以本篇文章就来实现一个多线程的例子。单线程webserver存在的问题请求只能串行处......
  • java多线程生产者消费者线程并发协作测试心得
    图11-17生产者消费者示意图产品classChicken{intid;publicChicken(intid){this.id=id;}}缓冲区(装产品)classContainer{//定......
  • 多线程
    JUC并发编程多线程三种创建方式继承Thread(Thread实现了Runnable接口)实现Runnable(这种方式需要将该实现类作为参数调用Thread对象)实现Callable线程的状态线程方法......
  • 多线程
    1、程序、进程、线程程序(program)是为了完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象进程(process)是程序的一次执行过程,或是正在运行的一......
  • CPU端多进程/多线程调用CUDA是否可以加速???
    相关:NVIDIA显卡cuda的多进程服务——MPS(Multi-ProcessService)tensorflow1.x——如何在C++多线程中调用同一个session会话tensorflow1.x——如何在python多线程中......
  • 多线程的异常处理
    1.异常在线程内部处理多线程使用过程中,在线程内部使用try...catch...是可以捕获异常的。但是外部使用try...catch...通常无法捕获异常,也就是说程序不会throw异常(异常被吞......
  • 线程同步-读者写者问题(多线程)
    问题描述    有读者和写者两个并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数......
  • Linux 关闭系统时间同步-timedatectl的使用
     源于一次项目需要修改系统时间,但是每次修改后又被同步回网络时间,找了好久发现是这个原因:NTP即NetworkTimeProtocol(网络时间协议),是一个互联网协议,用于同步计算机之间......
  • 微信小程序 解决 wx.request同步问题 方便开发 Promise方式
    统一提示信息/***统一提示信息*@authorlangjf*/paiAlert:function(title,confirmToUrl,cancelToUrl){wx.showModal({title:'温馨提......