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

线程的信号量和互斥量

文章目录

  • 线程的信号量
    • 初始化信号量: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执行的顺序。

使用流程:

  1. sem_init初始化信号量
  2. sem_post增加信号量
  3. 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: 10,表示信号量线程共享,多线程可以共同操作该信号量,要求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

使用流程:

  1. 初始化互斥量
  2. 锁住互斥量
  3. 解锁互斥量
  4. 销毁互斥量

初始化互斥量: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;
}

相关文章:

线程的信号量和互斥量

文章目录线程的信号量初始化信号量&#xff1a;sem_init减少信号量&#xff1a;sem_wait增加信号量&#xff1a;sem_post删除信号量&#xff1a;sem_destroy代码示例线程的互斥量初始化互斥量&#xff1a;pthread_mutex_init锁住互斥量&#xff1a;pthread_mutex_lock解锁互斥量…...

关于Linux,开源社区与国产化的本质区别

因为生产力驱动而非理想主义驱动。 开源运动的蓬勃发展来自于GNU(GNU is not unix)&#xff0c;RichardMatthewStallman领导着一群黑客&#xff0c;带着对比尔盖茨的鄙视&#xff0c;制定了GPL协议&#xff0c;以后人人都能从伟大的前人身上学习到源代码的精髓&#xff0c;让软…...

Win11下Linux子系统迁移方法及报错解决

Win11 将Linux子系统从C盘迁移到其他盘Win11下Linux子系统迁移方法及报错解决1、下载LxRunOffline2、ERROR&#xff1a;directory is not empty 报错解决参考链接Win11下Linux子系统迁移方法及报错解决 C盘满了&#xff0c;Ubuntu子系统占了100多G怎么办&#xff1f;直接将子系…...

python维护的一些基础方法

1】通过命令行查看python安装库的基本信息 pip show numpy # 查看python中numpy库的安装版本信息 2】python 环境的开发与维护 python的开发与C\MATLAB等最大的不同就是&#xff0c;python中版本的更新不对历史版本负责&#xff0c;就是说你以历史版本开发的python程序&#…...

C语言 数组元素的指针

1.一个变量有地址&#xff0c;一个数组包含若干个元素&#xff0c;每个数组元素都在内存中占用存储单元&#xff0c;它们都有相应的地址。 2.指针变量既然可以指向变量&#xff0c;当然也可以指向数组元素&#xff08;把某一元素的地址放入一个指针变量中&#xff09;。 3.所谓…...

(C语言)指针进阶

问&#xff1a;1. ( )&#xff0c;[ ]&#xff0c;->&#xff0c;&#xff0c;--&#xff0c;. &#xff0c;&#xff0a;的操作符优先级是怎么样的&#xff1f;2. Solve the problems&#xff1a;只有一个常量字符串与一个字符指针&#xff0c;该怎么打印常量字符串所有内容…...

DS期末复习卷(三)

选择题 某数据结构的二元组形式表示为A(D&#xff0c;R)&#xff0c;D{01&#xff0c;02&#xff0c;03&#xff0c;04&#xff0c;05&#xff0c;06&#xff0c;07&#xff0c;08&#xff0c;09}&#xff0c;R{r}&#xff0c;r{<01&#xff0c;02>&#xff0c;<01&a…...

Java链表模拟实现+LinkedList介绍

文章目录一、模拟实现单链表成员属性成员方法0&#xff0c;构造方法1&#xff0c;addFirst——头插2&#xff0c;addLast——尾插3&#xff0c;addIndex——在任意位置插入3.1&#xff0c;checkIndex——判断index合法性3.2&#xff0c;findPrevIndex——找到index-1位置的结点…...

MySQL——单表、多表查询

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varcha…...

关于表的操作 数据库(3)

目录 前期准备工作&#xff1a; 一、单表查询&#xff1a; 二、多表查询&#xff1a; 前期准备工作&#xff1a; 修改数据库的配置文件&#xff0c;&#xff0c;使其可以显示库名&#xff0c;其中//d代表当前使用的数据库名 注&#xff1a;vim /etc/my.cnf.d/mysql-server.c…...

C++:红黑树

红黑树的概念 红黑树是一棵二叉搜索树&#xff0c;但是红黑树通过增加一个存储位表示结点的颜色RED或BLACK。通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出2倍&#xff0c;因而是接近平衡的。 红黑树的性质 ⭐…...

每天一道算法题の中缀表达式

中缀表达式&#xff08;、-、*、/&#xff09; &#xff1a;中缀表达式是指操作符位于操作数之间的数学表达式。例如&#xff0c;在中缀表达式"2 3"中&#xff0c;操作符""位于操作数"2"和"3"之间。现给定一个中缀表达式&#xff0c…...

Dar语法基础-泛型

泛型 如果查看基本数组类型 List 的 API 文档&#xff0c;您会发现该类型实际上是 List<E>。 <…> 表示法将 List 标记为泛型&#xff08;或参数化&#xff09;类型——具有正式类型参数的类型。 按照惯例&#xff0c;大多数类型变量的名称都是单字母的&#xff0…...

rt-thread------串口(一)配置

系列文章目录 rt-thread 之 fal移植 rt-thread 之 生成工程模板 文章目录系列文章目录前言一、串口的配置step1&#xff1a;通过串口名字找到串口句柄step2&#xff1a;配置串口参数step3&#xff1a;设置串口接收回调函数step4&#xff1a;打开串口设备前言 UART&#xff08…...

Android - 自动系统签名

一、系统签名 以下是两类应用开发场景&#xff1a; 普通应用开发&#xff1a;使用公司自定义 keystore 进行签名&#xff0c;如&#xff1a;微信、支付宝系统应用开发&#xff1a;使用 AOSP 系统签名或厂商自定义 keystore 进行签名&#xff0c;如&#xff1a;设置、录音 系…...

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 生成输入信号 在汽车的电控软件开发中&#xff0c;经常会在Simulink模型内部进行单元测试。单元测试的本…...

云计算培训靠谱吗?

怎么算靠谱的培训呢&#xff1f; 举个例子&#xff1a; 我想参加云计算培训找个工作&#xff0c;机构满足了我的要求&#xff0c;有工作了&#xff0c;但是不是做云计算相关的。 小强也参加了云计算培训&#xff0c;想学好云计算成为技术大牛&#xff0c;最后专业学得普普通…...

力扣SQL刷题10

目录标题618. 学生地理信息报告--完全不会的新题型1097. 游戏玩法分析 V - 重难点1127. 用户购买平台--难且不会618. 学生地理信息报告–完全不会的新题型 max()函数的功效&#xff1a;&#xff08;‘jack’, null, null&#xff09;中得出‘jack’&#xff0c;&#xff08;nul…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...