线程的信号量和互斥量
文章目录
- 线程的信号量
- 初始化信号量:sem_init
- 减少信号量:sem_wait
- 增加信号量:sem_post
- 删除信号量:sem_destroy
- 代码示例
- 线程的互斥量
- 初始化互斥量:pthread_mutex_init
- 锁住互斥量:pthread_mutex_lock
- 解锁互斥量:pthread_mutex_unlock
- 销毁互斥量:pthread_mutex_destroy
- 代码示例
线程的信号量
原理简介:
线程的信号量和进程的类似,维护一个sem_t类型(本质是一个int类型的)的信号量,不同线程通过判断信号量的值,来决定是否进行继续运行,从而控制线程运行的先后顺序。比如信号量初始化成0,线程1调用sem_wait阻塞住,等待线程2调用sem_post将限号量增加之后,线程1被唤醒,从而实现线程1、2执行的顺序。
使用流程:
- sem_init初始化信号量
- sem_post增加信号量
- sem_wait判断并减少信号量
初始化信号量:sem_init
sem_init用于初始化信号量的初始值和作用范围。
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
Link with -pthread;
sem: 需要被初始化的信号量对象;
value: 初始值;
pshared: 1)0,表示信号量线程共享,多线程可以共同操作该信号量,要求sem变量的作用域能被多个线程访问到;2)非0,表示信号量进程共享,多进程可以共同操作该信号量,如果是父子进程,要求sem变量的作用域能被多个进程访问到,若父子进程,则可以直接访问,若没有关系的进程,那么sem要在共享内存中创建;
返回值: 成功,返回0;失败,返回-1,并置上errno;
减少信号量:sem_wait
sem_wait函数判断信号量是否大于0,如果大于0,则将信号量减一,并且立即返回,如果小于等于0,就阻塞在该函数,直到信号量大于0。
#include <semaphore.h>
int sem_wait(sem_t *sem);
sem: 待操作的信号量;
返回值: 成功,返回0;失败,返回-1,并置上errno
增加信号量:sem_post
sem_post用于给信号量加1
#include <semaphore.h>
int sem_post(sem_t *sem);
sem: 待操作的信号量;
返回值: 成功,返回0;失败,返回-1,并置上errno
删除信号量:sem_destroy
#include <semaphore.h>
int sem_destroy(sem_t *sem);
sem: 待操作的信号量;
返回值: 成功,返回0;失败,返回-1,并置上errno
代码示例
线程1先被创建,但是阻塞在信号量上,线程2后被创建,被运行后将信号量增加,然后线程1识别到信号量大于零,才执行后面的步骤。
#include <semaphore.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>sem_t sem;void * func1(void *arg)
{int ret;ret = sem_wait(&sem);if (ret != 0) {perror("sem_wait: ");return NULL;}printf("%s: pthread id: %ul\n", __func__, pthread_self());
}void * func2(void *arg)
{int ret;printf("%s: pthread id: %ul\n", __func__, pthread_self());ret = sem_post(&sem);if (ret != 0) {perror("sem_post: ");return NULL;}
}int
main(int argc, char **argv)
{int ret;pthread_t p1, p2;ret = sem_init(&sem, 0, 0);if (ret < 0) {perror("sem_init: ");return -1;}ret = pthread_create(&p1, NULL, &func1, NULL);if (ret != 0) {perror("pthread_create: ");return -1;}sleep(5);ret = pthread_create(&p2, NULL, &func2, NULL);if (ret != 0) {perror("pthread_create: ");return -1;}sleep(1);return 0;}
线程的互斥量
原理简介:
- 互斥量底层也是通过锁实现的,第一个线程访问互斥量的时候对互斥量加锁,后续线程加锁互斥量的时候会被阻塞,直到锁被释放
- 互斥量在POSIX中定义
- 互斥量是一种特殊的信号量,信号量是一个int数值,可以随意大小,互斥量只有0和1
使用流程:
- 初始化互斥量
- 锁住互斥量
- 解锁互斥量
- 销毁互斥量
初始化互斥量:pthread_mutex_init
互斥量用之前必须初始化:
//初始化方法1:使用默认属性,必须在定义的时候初始化,不可以先定义后初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//初始化方法2:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
mutex: 待初始化的互斥量;
attr: 参数,可以直接使用NULL;
返回值: 成功,返回0,失败,返回非0,并置上errno
锁住互斥量:pthread_mutex_lock
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex: 待锁住的互斥量;
返回值: 成功,返回0,失败,返回非0,并置上errno
解锁互斥量:pthread_mutex_unlock
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex: 待解锁的互斥量;
返回值: 成功,返回0,失败,返回非0,并置上errno;
销毁互斥量:pthread_mutex_destroy
互斥量用完了之后要释放
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex: 待销毁的互斥量;
返回值: 成功,返回0,失败,返回非0,并置上errno;
代码示例
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void * func1(void *arg)
{int ret;ret = pthread_mutex_lock(&mutex);if (ret != 0){perror("pthread_mutex_lock: ");return NULL;}printf("%s: pthread id: %ul\n", __func__, pthread_self());pthread_mutex_destroy(&mutex);
}void * func2(void *arg)
{int ret;printf("%s: pthread id: %ul\n", __func__, pthread_self());
}int
main(int argc, char **argv)
{int ret;pthread_t p1, p2;//ret = pthread_mutex_init(&mutex, NULL);//if (ret != 0) {// perror("pthread_mutex_init: ");// return -1;//}ret = pthread_mutex_lock(&mutex);if (ret != 0){perror("pthread_mutex_lock: ");return -1;}ret = pthread_create(&p1, NULL, &func1, NULL);if (ret != 0) {perror("pthread_create: ");return -1;}sleep(5);ret = pthread_create(&p2, NULL, &func2, NULL);if (ret != 0) {perror("pthread_create: ");return -1;}sleep(1);ret = pthread_mutex_unlock(&mutex);if (ret != 0){perror("pthread_mutex_lock: ");return -1;}sleep(1);return 0;
}
相关文章:
线程的信号量和互斥量
文章目录线程的信号量初始化信号量:sem_init减少信号量:sem_wait增加信号量:sem_post删除信号量:sem_destroy代码示例线程的互斥量初始化互斥量:pthread_mutex_init锁住互斥量:pthread_mutex_lock解锁互斥量…...
关于Linux,开源社区与国产化的本质区别
因为生产力驱动而非理想主义驱动。 开源运动的蓬勃发展来自于GNU(GNU is not unix),RichardMatthewStallman领导着一群黑客,带着对比尔盖茨的鄙视,制定了GPL协议,以后人人都能从伟大的前人身上学习到源代码的精髓,让软…...
Win11下Linux子系统迁移方法及报错解决
Win11 将Linux子系统从C盘迁移到其他盘Win11下Linux子系统迁移方法及报错解决1、下载LxRunOffline2、ERROR:directory is not empty 报错解决参考链接Win11下Linux子系统迁移方法及报错解决 C盘满了,Ubuntu子系统占了100多G怎么办?直接将子系…...
python维护的一些基础方法
1】通过命令行查看python安装库的基本信息 pip show numpy # 查看python中numpy库的安装版本信息 2】python 环境的开发与维护 python的开发与C\MATLAB等最大的不同就是,python中版本的更新不对历史版本负责,就是说你以历史版本开发的python程序&#…...
C语言 数组元素的指针
1.一个变量有地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。 2.指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放入一个指针变量中)。 3.所谓…...
(C语言)指针进阶
问:1. ( ),[ ],->,,--,. ,*的操作符优先级是怎么样的?2. Solve the problems:只有一个常量字符串与一个字符指针,该怎么打印常量字符串所有内容…...
DS期末复习卷(三)
选择题 某数据结构的二元组形式表示为A(D,R),D{01,02,03,04,05,06,07,08,09},R{r},r{<01,02>,<01&a…...
Java链表模拟实现+LinkedList介绍
文章目录一、模拟实现单链表成员属性成员方法0,构造方法1,addFirst——头插2,addLast——尾插3,addIndex——在任意位置插入3.1,checkIndex——判断index合法性3.2,findPrevIndex——找到index-1位置的结点…...
MySQL——单表、多表查询
一、单表查询 素材: 表名:worker-- 表中字段均为中文,比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varcha…...
关于表的操作 数据库(3)
目录 前期准备工作: 一、单表查询: 二、多表查询: 前期准备工作: 修改数据库的配置文件,,使其可以显示库名,其中//d代表当前使用的数据库名 注:vim /etc/my.cnf.d/mysql-server.c…...
C++:红黑树
红黑树的概念 红黑树是一棵二叉搜索树,但是红黑树通过增加一个存储位表示结点的颜色RED或BLACK。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出2倍,因而是接近平衡的。 红黑树的性质 ⭐…...
每天一道算法题の中缀表达式
中缀表达式(、-、*、/) :中缀表达式是指操作符位于操作数之间的数学表达式。例如,在中缀表达式"2 3"中,操作符""位于操作数"2"和"3"之间。现给定一个中缀表达式,…...
Dar语法基础-泛型
泛型 如果查看基本数组类型 List 的 API 文档,您会发现该类型实际上是 List<E>。 <…> 表示法将 List 标记为泛型(或参数化)类型——具有正式类型参数的类型。 按照惯例,大多数类型变量的名称都是单字母的࿰…...
rt-thread------串口(一)配置
系列文章目录 rt-thread 之 fal移植 rt-thread 之 生成工程模板 文章目录系列文章目录前言一、串口的配置step1:通过串口名字找到串口句柄step2:配置串口参数step3:设置串口接收回调函数step4:打开串口设备前言 UART(…...
Android - 自动系统签名
一、系统签名 以下是两类应用开发场景: 普通应用开发:使用公司自定义 keystore 进行签名,如:微信、支付宝系统应用开发:使用 AOSP 系统签名或厂商自定义 keystore 进行签名,如:设置、录音 系…...
SSH 服务详解 (八)-- vscode 通过 SSH 远程连接 linux 服务器
vscode 通过 SSH 远程连接 linux 服务器 SSH服务详解(一)–Linux SSH 服务器与客户端的安装与启动 SSH服务详解(二)–使用私钥登录 SSH 服务器(免密登录) SSH 服务详解 (三)-- 使用 SSH 代理 SSH 服务详解 (四)-- 本地调用远程主机的命令 SSH 服务详解 (五)-- 远程文件拷贝…...
【PTA Advanced】1060 Are They Equal(C++)
目录 题目 Input Specification: Output Specification: Sample Input 1: Sample Output 1: Sample Input 2: Sample Output 2: 思路 C 知识点UP 代码 题目 If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered …...
仿真与测试:通过Signal Builder模块生成输入信号
本文研究通过Signal Builder模块生成输入信号的方法。 文章目录1 生成输入信号2 仿真过程2.1 搭建被测模型2.2 搭建Signal Builder输入模块2.3 配置仿真log及仿真3 总结1 生成输入信号 在汽车的电控软件开发中,经常会在Simulink模型内部进行单元测试。单元测试的本…...
云计算培训靠谱吗?
怎么算靠谱的培训呢? 举个例子: 我想参加云计算培训找个工作,机构满足了我的要求,有工作了,但是不是做云计算相关的。 小强也参加了云计算培训,想学好云计算成为技术大牛,最后专业学得普普通…...
力扣SQL刷题10
目录标题618. 学生地理信息报告--完全不会的新题型1097. 游戏玩法分析 V - 重难点1127. 用户购买平台--难且不会618. 学生地理信息报告–完全不会的新题型 max()函数的功效:(‘jack’, null, null)中得出‘jack’,(nul…...
SpringCloud Eureka停更了,我为什么还在用它做微服务注册中心?
SpringCloud Eureka停更后,为什么它仍是微服务架构的隐秘王牌? 当Netflix在2018年宣布停止维护Eureka时,整个Java微服务社区都为之震动。五年过去了,这个"过时"的组件却依然活跃在众多企业的生产环境中。上周我参与了一…...
别再为3DGS头疼了!手把手教你用COLMAP+UnityGaussianSplatting从照片到实时场景(避坑指南)
3D高斯重建实战:从照片到Unity实时渲染的全流程避坑指南 当我在工作室第一次尝试将手机拍摄的照片转换成可交互的3D场景时,经历了无数次COLMAP崩溃、点云缺失和Unity插件报错。这种挫败感让我意识到,3D高斯重建技术虽然强大,但工具…...
Phi-4-Reasoning-Vision开源大模型实践:图文多模态输入格式与Phi-4模型要求对齐
Phi-4-Reasoning-Vision开源大模型实践:图文多模态输入格式与Phi-4模型要求对齐 1. 项目概述 Phi-4-Reasoning-Vision是一款基于微软Phi-4-reasoning-vision-15B多模态大模型开发的高性能推理工具,专为双卡RTX 4090环境优化。该工具严格遵循官方SYSTEM…...
从猫狗识别到工业质检:深入理解PyTorch中的sample_weight,让模型更‘关注’关键样本
从猫狗识别到工业质检:深入理解PyTorch中的sample_weight,让模型更‘关注’关键样本 在工业质检和医疗影像分析中,某些样本的误判代价可能比其他样本高出一个数量级。想象一下,在半导体缺陷检测中漏判一个微小裂纹,或在…...
AXI非对齐访问实战指南:从WSTRB信号到DMA数据搬运的避坑细节
AXI非对齐访问实战指南:从WSTRB信号到DMA数据搬运的避坑细节 在FPGA与ASIC设计中,AXI总线作为AMBA协议族的核心成员,其非对齐访问特性常被开发者视为"双刃剑"。当处理摄像头YUV数据、音频采样流或网络封包等非规整数据时࿰…...
Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF小白友好测评:vLLM部署是否真的简单?生成效果如何?
Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF小白友好测评:vLLM部署是否真的简单?生成效果如何? 1. 引言:从零开始的模型部署体验 作为一个刚接触大模型部署的新手,我最近尝试用vLLM部署了Qwen3-4B-Thinking-25…...
实战剖析:利用EFDD与VeraCrypt破解加密磁盘文件
1. 加密磁盘破解的核心原理 当你面对一个加密的VeraCrypt容器时,第一反应可能是"这数据还能救吗?"。我处理过几十起类似案例,可以明确告诉你:只要获取到内存转储文件,就有很大概率能还原出加密密钥。这里的关…...
基于Spring AI与Alibaba的智能客服系统:架构设计与实战避坑指南
传统客服系统,尤其是那些基于硬编码规则引擎的,相信很多开发者都维护过。这类系统通常有几个让人头疼的“老大难”问题:用户稍微换个说法,机器人就“听不懂”了,意图识别率低得可怜;业务高峰期,…...
asp毕业设计下载(全套源码+配套论文)——基于asp+access的会员管理系统设计与实现
基于aspaccess的会员管理系统设计与实现(毕业论文程序源码) 大家好,今天给大家介绍基于aspaccess的会员管理系统设计与实现,更多精选毕业设计项目实例见文末哦。 文章目录: 基于aspaccess的会员管理系统设计与实现&a…...
大模型Prompt实战指南:从基础到高阶的提问艺术
1. 为什么Prompt提问技巧如此重要? 第一次用ChatGPT时,我直接问"怎么写工作总结",结果得到一篇泛泛而谈的模板。后来学会在问题里加上"我是一名互联网产品经理,需要向CTO汇报季度工作",回答立刻精…...
