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://www.pswp.cn/web/97874.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/97874.shtml
英文地址,请注明出处:http://en.pswp.cn/web/97874.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业自动化领域的“超级跑车”:西门子TDC系统深度解析与实战架构

工业自动化领域的“超级跑车”&#xff1a;西门子TDC系统深度解析与实战架构 文章目录 工业自动化领域的“超级跑车”&#xff1a;西门子TDC系统深度解析与实战架构引言&#xff1a;当普通PLC遇到性能瓶颈第一章&#xff1a;认识TDC——它不是简单的“大型PLC”1.1 TDC究竟是什…

MySQL高阶查询语句与视图实战指南

MySQL高阶查询语句与视图实战指南 文章目录MySQL高阶查询语句与视图实战指南一、常用高阶查询技巧1. 按关键字排序&#xff08;ORDER BY&#xff09;基础用法进阶用法&#xff1a;多字段排序条件过滤2. 区间判断与去重&#xff08;AND/OR DISTINCT&#xff09;区间判断&#x…

解决Pytest参数化测试中文显示乱码问题:两种高效方法

在使用Pytest进行参数化测试时&#xff0c;许多开发者都会遇到一个常见但令人头疼的问题&#xff1a;当测试用例的ids参数包含中文字符时&#xff0c;控制台输出会出现乱码。这不仅影响了测试报告的可读性&#xff0c;也给测试结果的分析带来了困难。本文将深入探讨这个问题&am…

基于SpringBoot的校园流浪动物救助平台【spring boot实战项目、Java毕设、Java项目、Java实战】

&#x1f496;&#x1f496;作者&#xff1a;计算机毕业设计小途 &#x1f499;&#x1f499;个人简介&#xff1a;曾长期从事计算机专业培训教学&#xff0c;本人也热爱上课教学&#xff0c;语言擅长Java、微信小程序、Python、Golang、安卓Android等&#xff0c;开发项目包括…

利用kimi k2编写postgresql协议服务端的尝试

美团龙猫还是很有自知之明的 提问请用C编写postgresql协议服务端&#xff0c;能接收psql客户端或其他采用postgresql协议的工具的请求&#xff0c;实现将用户请求打印在控制台&#xff0c;并把回应发给客户端回答 抱歉&#xff0c;我无法为您编写完整的 PostgreSQL 协议服务端。…

医疗 AI 再突破:辅助诊断准确率超 90%,但落地医院仍面临数据安全与临床信任难题

一、引言&#xff08;一&#xff09;医疗 AI 发展背景在数字化与智能化浪潮的席卷下&#xff0c;医疗领域正经历着深刻变革&#xff0c;人工智能&#xff08;AI&#xff09;技术的融入成为这场变革的关键驱动力。近年来&#xff0c;医疗 AI 辅助诊断技术取得重大突破&#xff0…

Rocky Linux10.0安装zabbix7.4详细步骤

安装Rocky Linux10.0系统 请参考Rocky Linux10.0安装教程-CSDN博客 查看当前系统版本 cat /etc/*release 安装数据库 安装zabbix之前&#xff0c;需要先安装一个数据库来承载zabbix的数据。这里我选择在本机直接安装一个MariaDB数据库。 Rocky Linux10.0系统默认不包含MySQ…

JDBC插入数据

文章目录视频&#xff1a;JDBC插入数据环境准备写插入数据属性配置属性配置视频&#xff1a;JDBC插入数据 环境准备 MySQL环境 小皮面板 提供MySQL环境 写插入数据 属性配置 声明变量 属性配置 # . properties 是一个特俗的map 集合 # key : 字符串 value : 字符串…

GPU 服务器压力测试核心工具全解析:gpu-burn、cpu-burn 与 CUDA Samples

在 GPU 服务器的性能验证、稳定性排查与运维管理中,压力测试是关键环节,可有效检测硬件极限性能、散热效率及潜在故障。以下从工具原理、核心功能、使用场景等维度,详细介绍三款核心测试工具,帮助用户系统掌握 GPU 服务器压力测试方法。 一、GPU 专属压力测试工具:gpu-bu…

Python进程和线程——多线程

前面提到过进程是由很多线程组成的&#xff0c;那么今天廖老师就详细解释了线程是如何运行的。首先&#xff0c;&#xff0c;Python的标准库提供了两个模块&#xff1a;_thread和threading&#xff0c;_thread是低级模块&#xff0c;threading是高级模块&#xff0c;对_thread进…

【MySQL|第九篇】视图、函数与优化

目录 十、视图 1、简单视图&#xff1a; 2、复杂视图&#xff1a; 3、视图更新&#xff1a; 十一、函数 1、函数创建&#xff1a; 十二、数据库优化 1、索引优化&#xff1a; 2、查询优化&#xff1a; 3、设计优化&#xff1a; 十、视图 在 MySQL 中&#xff0c;视图…

使用Docker和虚拟IP在一台服务器上灵活部署多个Neo4j实例

使用Docker和虚拟IP在一台服务器上灵活部署多个Neo4j实例 前言 在现代应用开发中&#xff0c;图数据库Neo4j因其强大的关系处理能力而备受青睐。但有时候我们需要在同一台服务器上运行多个Neo4j实例&#xff0c;比如用于开发测试、多租户环境或者A/B测试。传统的端口映射方式…

K8s学习笔记(一):Kubernetes架构-原理-组件

Kubernetes&#xff08;简称 K8s&#xff09;是一款开源的容器编排平台&#xff0c;核心目标是实现容器化应用的自动化部署、扩展、故障恢复和运维管理。其设计遵循 “主从架构”&#xff08;Control Plane Node&#xff09;&#xff0c;组件分工明确&#xff0c;通过 “声明式…

ensp配置学习笔记 比赛版 vlan 静态路由 ospf bgp dhcp

学习配置VLAN 虚拟局域网&#xff0c;目的让两台在同一网段的设备&#xff0c;在交换机中访问。基础指令&#xff1a;sys 进入系统 sysname R1 修改交换机名字为R1 display cur 查看数据、端口等交换机信息 &#xff08;在端口中&#xff0c;可以直接display this 可以直接看…

仓颉编程语言青少年基础教程:enum(枚举)类型和Option类型

仓颉编程语言青少年基础教程&#xff1a;enum&#xff08;枚举&#xff09;类型和Option类型enum 和 Option 各自解决一类“语义级”问题&#xff1a;enum 让“取值只在有限集合内”的约束从注释变成编译器强制&#xff1b;Option 让“值可能不存在”的语义显式化。enum类型enu…

javaEE-Spring IOCDI

目录 1、什么是Spring&#xff1a; 2.什么是IoC: 3. 什么是控制反转呢? 4.IoC容器具备以下优点: 5.DI是什么&#xff1a; 依赖注⼊方法&#xff1a; 三种注入方法的优缺点&#xff1a; Autowired注解注入存在的问题&#xff1a; Autowired和Resource的区别&#xff…

TensorFlow Lite 全面解析:端侧部署方案与PyTorch Mobile深度对比

1 TensorFlow Lite 基础介绍 TensorFlow Lite (TFLite) 是 Google 为移动设备&#xff08;Android, iOS&#xff09;、微控制器&#xff08;Microcontrollers&#xff09;和其他嵌入式设备&#xff08;如 Raspberry Pi&#xff09;开发的轻量级深度学习推理框架。它的核心目标是…

mapbox进阶,使用jsts实现平角缓冲区

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言 1.1 ☘️mapboxgl.Map 地图对象 1.2 ☘️mapboxgl.Map style属性 1.3 ☘️jsts myBufferOp 缓冲区生成对对象 …

linux装好显卡后如何检查

背景&#xff1a;客户通知装好了显卡&#xff0c;我们去机器上查看一下一. 使用到的命令 watch -n 1 nvidia-smi 可实时查看gpu的使用率nvidia-smi 之查看一次 二、查看内存和显存 内存使用命令 free -h,显存使用 nvidia-smi 这只是查看的navidia, 其他品牌的会不一样

人工智能深度学习——卷积神经网络(CNN)

一、图像卷积运算 对图像矩阵与滤波器矩阵进行对应相乘再求和运算&#xff0c;转化得到新的矩阵。 作用&#xff1a;快速定位图像中某些边缘特征 英文&#xff1a;convolution&#xff08;CNN&#xff09;池化层实现维度缩减 池化&#xff1a;按照一个固定规则对图像矩阵进行处…