当前位置: 首页 > news >正文

信号量主要API及综合应用

1.信号量概述

信号量是一个底层核心模块【int】类型变量,记录当前信号量数据。

信号量 P 操作 (sem_wait)

        线程检测对应信号量底层 int 数据数值,如果大于 0,当前线程获得 CPU 执行权,同时将信号量底层 int 数据-1 操作。

如果底层数据为 0,当前线程无法获取 CPU 执行权,进入阻塞状态。同时等待信号量 > 0

信号量 V 操作 (sem_post)

        线程任务执行完毕,执行 V 操作,对当信号量底层 int 数据 +1,相当于释放 CPU 执行权。

信号量可以控制线程互斥和线程同步。

2.信号量相关API

2.1sem_init初始化

#include <semaphore.h> 
int sem_init(sem_t *sem, int pshared, unsigned int value)

函数功能:

        用于初始化一个信号量变量,提供必要的参数,限制当前信号量是针对于【线程操作】还是【进程操作】

函数参数:

        sen_t *sem: 信号量变量地址

        int  pshared: 控制值当前信号量,限制内容为线程还是进程,线程参数要求为 0, 不等于 0 为进程间操作。建议 0 线程, 1 进程。

        unsigned int value: 信号量初始化数据,通常情况下为 1 

返回值:

        成功返回 0

        失败返回 -1

2.2sem_wait   P操作/等待操作

#include <semaphore.h> 
int sem_wait(sem_t *sem)

函数功能:

        信号量 P 操作,当前信号量-1。

        如果为 0 当前线程/进程进入阻塞状态。

        如果不为 0,信号量 -= 1,同时可以执行目标线程/进程代码。

函数参数:

        sem_t *sem: 信号量变量地址

返回值类型:

        成功返回 0

        失败返回 -1

2.3sem_post  V操作/释放操作

#include <semaphore.h> 
int sem_post(sem_t *sem)

函数功能:

        信号量 V 操作,当前信号量 +1

        信号量不为 0,相当于解除与当前信号量相关的其他线程/进程阻塞状态

函数参数:

        sem_t *sem : 信号量变量地址

返回值类型

        成功返回 0

        失败返回 -1

2.4sem_destroy  销毁操作

#include <semaphore.h> 
int sem_destroy(sem_t *sem)

函数功能:

        销毁当前信号量变量

函数参数:

        sem_t  *sem: 信号量变量地址

返回值类型

        成功返回 0

        失败返回 -1

2.5信号量的操作案例

将上面的信号量函数进行综合应用

2.5.1信号量互斥控制

相当于互斥锁的作用

#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
sem_t sem;
void *threadA_task(void *arg);
void *threadB_task(void *arg);
void *threadC_task(void *arg);
void print_string(const char *str);
// 线程 A 对应的线程【句柄】类型
pthread_t tid1;
// 线程 B 对应的线程【句柄】类型
pthread_t tid2;
// 线程 C 对应的线程【句柄】类型
pthread_t tid3;
int main(int argc, char const *argv[])
{int status = 0;/*1. 初始化信号量初始化当前信号量,对应的控制目标为线程,初始化数据为 1int sem_init (sem_t *__sem, int __pshared, unsigned int __value)*/status = sem_init(&sem, 0, 3);//int  pshared: 控制值当前信号量,限// 制内容为线程还是进程,线程参数要求为 0, //不等于 0 为进程间操作。建议 0 线程, 1 进程。if (status){printf("semaphore init failed!\n");_exit(1);}status = pthread_create(&tid1, NULL, threadA_task, "Hello World!");if (status){printf("pthread_create threadA failed!\n");_exit(1);}status = pthread_create(&tid2, NULL, threadB_task, "Hello HH!");if (status){printf("pthread_create threadB failed!\n");_exit(1);}status = pthread_create(&tid3, NULL, threadC_task, "Hello GL!");if (status){printf("pthread_create threadC failed!\n");_exit(1);}pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);return 0;
}
void *threadA_task(void *arg)
{// 信号量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信号量 V 操作sem_post(&sem);
}
void *threadB_task(void *arg)
{// 信号量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信号量 V 操作sem_post(&sem);
}
void *threadC_task(void *arg)
{// 信号量 P 操作sem_wait(&sem);print_string((const char *)arg);// 信号量 V 操作sem_post(&sem);
}
void print_string(const char *str)
{while (*str){printf("%c\n", *str);sleep(1);str += 1;}
}

2.5.1信号量执行流程控制

#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <semaphore.h>
sem_t sem1;
sem_t sem2;
sem_t sem3;
void *threadA_task(void *arg);
void *threadB_task(void *arg);
void *threadC_task(void *arg);
void print_string(const char *str);
// 线程 A 对应的线程【句柄】类型
pthread_t tid1;
// 线程 B 对应的线程【句柄】类型
pthread_t tid2;
// 线程 C 对应的线程【句柄】类型
pthread_t tid3;
int main(int argc, char const *argv[])
{int status = 0;/*1. 初始化信号量初始化当前信号量,对应的控制目标为线程,初始化数据为 1int sem_init (sem_t *__sem, int __pshared, unsigned int __value)*/status = sem_init(&sem1, 0, 1);if (status){printf("semaphore init failed!\n");_exit(1);}status = sem_init(&sem2, 0, 0);if (status){printf("semaphore init failed!\n");_exit(1);}status = sem_init(&sem3, 0, 0);if (status){printf("semaphore init failed!\n");_exit(1);}status = pthread_create(&tid1, NULL, threadA_task, "Hello World!");if (status){printf("pthread_create threadA failed!\n");_exit(1);}status = pthread_create(&tid2, NULL, threadB_task, "Hello HH!");if (status){printf("pthread_create threadB failed!\n");_exit(1);}status = pthread_create(&tid3, NULL, threadC_task, "Hello GL!");if (status){printf("pthread_create threadC failed!\n");_exit(1);}pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);// 线程销毁pthread_cancel(tid1);pthread_cancel(tid2);pthread_cancel(tid3);// 信号量销毁sem_destroy(&sem1);sem_destroy(&sem2);sem_destroy(&sem3);return 0;
}
void *threadA_task(void *arg)
{// sem1 信号量 P 操作sem_wait(&sem1);print_string((const char *)arg);// sem2 信号量 V 操作sem_post(&sem2);
}
void *threadB_task(void *arg)
{// sem2 信号量 P 操作sem_wait(&sem2);print_string((const char *)arg);// sem3 信号量 V 操作sem_post(&sem3);
}
void *threadC_task(void *arg)
{// sem3 信号量 P 操作sem_wait(&sem3);print_string((const char *)arg);// sem1 信号量 V 操作sem_post(&sem1);
}
void print_string(const char *str)
{printf("%s\n", str);sleep(5);
}


文章转载自:

http://1pfPXOs1.xrrjb.cn
http://ho3lkGzk.xrrjb.cn
http://2GAf6kvA.xrrjb.cn
http://7Kwkagku.xrrjb.cn
http://CLW6cyc6.xrrjb.cn
http://7z0LQeNW.xrrjb.cn
http://hv8VXtrI.xrrjb.cn
http://2xwaEUDi.xrrjb.cn
http://JO9PzqeN.xrrjb.cn
http://fmJIOTJM.xrrjb.cn
http://00X0EeNL.xrrjb.cn
http://t8qgS1m0.xrrjb.cn
http://rNk6TaXB.xrrjb.cn
http://pFnUxd78.xrrjb.cn
http://nppnDy9S.xrrjb.cn
http://cctNek0N.xrrjb.cn
http://FoBUFrB0.xrrjb.cn
http://qdyfEoqD.xrrjb.cn
http://lfPX6fMu.xrrjb.cn
http://odGLSigb.xrrjb.cn
http://rPg1XjTK.xrrjb.cn
http://luxlGbLC.xrrjb.cn
http://HNcmL9PF.xrrjb.cn
http://wYCjwKxQ.xrrjb.cn
http://nNESEj5m.xrrjb.cn
http://28Kmg1E7.xrrjb.cn
http://vNkQQmWN.xrrjb.cn
http://4LrLLhKw.xrrjb.cn
http://wpYSWSZP.xrrjb.cn
http://bcx67ulO.xrrjb.cn
http://www.dtcms.com/a/385600.html

相关文章:

  • 【开题答辩全过程】以 B站用户视频喜好倾向数据分析系统为例,包含答辩的问题和答案
  • ARM架构学习6.2——中断理解
  • 搭建Qt5.14.2+msvc2017_x64项目测试Opencv4.10功能
  • Steger 算法 的原理和流程
  • WD5030K:一款7-30V宽输入范围、12A高效同步降压DC-DC转换器芯片详解
  • 《2025年AI产业发展十大趋势报告》五十七
  • 滴滴试点返程费自主议价将会怎么改变市场?
  • 【嵌入式原理系列-第八篇】USART从原理到配置全解析
  • Python4-seaborn
  • 使用 Aamzon Step Functions 重构无服务器工作流
  • 模电基础:场效应管
  • Typescript工具类型
  • Spring异步编程- 浅谈 Reactor 核心操作符
  • 21.5 单卡24G训7B大模型!HuggingFace TRL+QLoRA实战,3倍提速显存直降70%
  • git中,如果在文件夹A下有文件夹B、C文件夹,现在在A下创建仓库,连接远程仓库,那么如何在提交的时候忽略B、C,排除对B、C管理
  • Java Web 入门实战:SpringBoot+Spring MVC 从 0 到 1 学习指南
  • 电磁流量计可靠品牌之选,基恩士提供多样化解决方案
  • 三大基础无源电子元件——电阻(R)、电感(L)、电容(C)
  • Baklib:从传统到AI驱动的新一代数字体验平台
  • 机器视觉在人形机器人中有哪些检测应用
  • Java的Arrays类
  • 每天认识一个电子器件之LED灯
  • 每日前端宝藏库 | anime.js⏳✨
  • CSS脉冲光环动画效果
  • C++ 之【C++11的简介】(可变参数模板、lambda表达式、function\bind包装器)
  • 【基础组件 and 网络编程】对 DPDK 的 MPMC 无锁队列 rte-ring 组件的思考分析(同时也是实战原子操作的好机会)
  • ingress-nginx-controller 414 Request—URI Too Large
  • Java 定时任务与分布式调度工具分析
  • 【热点】最优传输(Optimal Transport)及matlab案例
  • 用 Kotlin 玩转 Protocol Buffers(proto3)