详解信号量机制

信号量(Semaphore)是一种用于多线程或多进程同步的机制,由荷兰计算机科学家 Edsger Dijkstra 提出。信号量的核心思想是通过一个整数值来控制对共享资源的访问,避免竞争条件(Race Condition)。信号量的操作主要包括 P 操作(等待)和 V 操作(释放),分别对应 sem_wait()sem_post()


1. 信号量的基本概念

  • 信号量值
    • 信号量是一个非负整数,表示可用资源的数量。
    • 当信号量值为 0 时,表示没有可用资源,线程或进程需要等待。
  • P 操作(Proberen,尝试)
    • 将信号量值减 1。
    • 如果信号量值小于 0,则线程或进程阻塞,直到信号量值大于 0。
  • V 操作(Verhogen,增加)
    • 将信号量值加 1。
    • 如果有线程或进程在等待信号量,则唤醒其中一个。

2. 信号量的类型

  • 二进制信号量
    • 信号量的值只能是 0 或 1。
    • 类似于互斥锁(Mutex),用于实现临界区的互斥访问。
  • 计数信号量
    • 信号量的值可以是任意非负整数。
    • 用于控制多个资源的访问。

3. 信号量的操作

(1)初始化信号量
  • 使用 sem_init() 初始化信号量。
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    
    • sem:信号量对象。
    • pshared:是否在进程间共享(0 表示线程间,非 0 表示进程间)。
    • value:信号量的初始值。
(2)P 操作(sem_wait
  • 将信号量值减 1,如果信号量值为 0,则阻塞。
    int sem_wait(sem_t *sem);
    
(3)V 操作(sem_post
  • 将信号量值加 1,并唤醒等待的线程或进程。
    int sem_post(sem_t *sem);
    
(4)销毁信号量
  • 使用 sem_destroy() 销毁信号量。
    int sem_destroy(sem_t *sem);
    

4. 信号量的使用示例

(1)二进制信号量(实现互斥锁)
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>sem_t sem; // 信号量
int shared_data = 0;void* thread_func(void* arg) {sem_wait(&sem); // P 操作shared_data += 10;printf("Thread updated shared_data: %d\n", shared_data);sem_post(&sem); // V 操作return NULL;
}int main() {pthread_t tid1, tid2;sem_init(&sem, 0, 1); // 初始化信号量,初始值为 1pthread_create(&tid1, NULL, thread_func, NULL);pthread_create(&tid2, NULL, thread_func, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL);sem_destroy(&sem); // 销毁信号量return 0;
}
(2)计数信号量(控制资源访问)
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>#define MAX_RESOURCES 3sem_t sem; // 信号量void* thread_func(void* arg) {sem_wait(&sem); // P 操作printf("Thread acquired resource\n");sleep(1); // 模拟资源使用printf("Thread released resource\n");sem_post(&sem); // V 操作return NULL;
}int main() {pthread_t tid[5];sem_init(&sem, 0, MAX_RESOURCES); // 初始化信号量,初始值为 3for (int i = 0; i < 5; i++) {pthread_create(&tid[i], NULL, thread_func, NULL);}for (int i = 0; i < 5; i++) {pthread_join(tid[i], NULL);}sem_destroy(&sem); // 销毁信号量return 0;
}

5. 信号量的应用场景

  • 互斥访问
    • 使用二进制信号量实现临界区的互斥访问。
  • 资源池管理
    • 使用计数信号量管理有限资源(如数据库连接池、线程池)。
  • 生产者-消费者问题
    • 使用信号量同步生产者和消费者线程。
  • 读者-写者问题
    • 使用信号量控制读者和写者的访问顺序。

6. 信号量的注意事项

  • 死锁
    • 如果多个线程或进程互相等待对方释放信号量,可能导致死锁。
  • 优先级反转
    • 低优先级线程持有信号量时,高优先级线程可能被阻塞。
  • 信号量泄漏
    • 确保每次 sem_wait() 后都有对应的 sem_post(),否则可能导致信号量泄漏。

总结

  • 信号量:是一种同步机制,用于控制对共享资源的访问。
  • P 操作:等待信号量,减少信号量值。
  • V 操作:释放信号量,增加信号量值。
  • 应用场景:互斥访问、资源池管理、生产者-消费者问题等。

信号量是多线程和多进程编程中非常重要的工具,合理使用可以有效避免竞争条件和实现复杂的同步逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/16479.html

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

相关文章

Linux之kernel(1)系统基础理论(2)

Linux之Kernel(1)系统基础理论(2) Author: Once Day Date: 2025年2月10日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: Linux内核知识_Once-Day的…

git本地建的分支,删除后内容还能找回

前提&#xff1a; 需要有commit 动作 1、git reflog 命令查看所有分支操作记录&#xff1b; 2、git checkout -b 命令创建一个新的分支&#xff0c;将其指向被删除分支的最后一个提交记录‌&#xff1b; git checkout -b <branch-name> <commit-hash>旨在分享~…

【每日一题 | 2025】2.3 ~ 2.9

个人主页&#xff1a;GUIQU. 归属专栏&#xff1a;每日一题 文章目录 1. 【2.3】P8784 [蓝桥杯 2022 省 B] 积木画2. 【2.4】P8656 [蓝桥杯 2017 国 B] 对局匹配3. 【2.5】[ABC365D] AtCoder Janken 34. 【2.6】P8703 [蓝桥杯 2019 国 B] 最优包含5. 【2.7】P8624 [蓝桥杯 2015…

Unity URP后处理在Game窗口不显示

摄像机勾选这个就可以了&#xff1a; 参考&#xff1a;UNITY3D URP与后处理,在game窗口不显示问题_unity urp 半透明材质game看不到-CSDN博客

Java进阶14 TCP日志枚举

Java进阶14 TCP&日志&枚举 一、网络编程TCP Java对基于TCP协议得网络提供了良好的封装&#xff0c;使用Socket对象来代表两端的通信端口&#xff0c;并通过Socket产生IO流来进行网络通信。 1、TCP协议发数据 1.1 构造方法 方法 说明 Socket(InetAddress address…

C#02项目——Checked用法

知识点 本项目用到的知识点包括&#xff1a; checked。主要用来处理溢出错误 Try.Prarse。将数字的字符串表示形式转换为其等效的 32 位有符号整数。 返回值指示转换是否成功 public static bool TryParse (string? s, out int result);Try…Catch。用于捕捉异常&#xff0c…

WPF 设置宽度为 父容器 宽度的一半

方法1&#xff1a;使用 绑定和转换器 实现 创建类文件 HalfWidthConverter public class HalfWidthConverter : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){if (value is double width){return width / 4…

Windows 系统 GDAL库 配置到 Qt 上

在地理信息开发中广泛使用的开源库&#xff0c;GDAL(Geospatial Data Abstraction Library&#xff09;)库提供了读取和处理各种地理空间数据格式的能力。 准备阶段 下载 GDAL 库&#xff1a;前往 GDAL 的官方网站&#xff08;https://www.gisinternals.com/&#xff09;下载…

自己动手实现一个简单的Linux AI Agent

大模型带我们来到了自然语言人机交互的时代 1、安装本地大模型进行推理 下载地址&#xff1a; https://ollama.com/download 部署本地deepseek和嵌入模型 ollama run deepseek-r1:7b2、制定Linux操作接口指令规范 3、编写大模型对话工具 #!/usr/bin/python3 #coding: utf-8…

豆包MarsCode “一键Apply”功能测评:编程效率革新利器

本文 前言功能亮点1. 告别重复操作2. 精准问题解决3. 助力新项目开发4.代码快速切换5.注释快速生成&#xff0c;一键Apply直接粘贴 使用体验总结 本文正在参加豆包MarsCode上新Apply体验活动 前言 在当今快节奏的编程开发领域&#xff0c;效率无疑是开发者们追求的核心目标之一…

SpringBoot中的Javaconfig

为什么要使用Javaconfig&#xff1f; 如果要声明的bean对象&#xff0c;来自于第三方jar包&#xff08;不是自定义的&#xff09;&#xff0c;无法使用Component 及衍生注解来声明bean&#xff0c;因为第三方的jar一般不可写&#xff0c;需要使用注解Configuration和Bean注解来…

ThinkPHP8视图赋值与渲染

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 在控制器操作中&#xff0c;使用view函数可以传入视图…

笔记4——列表list

列表list list&#xff1a;一种有序的集合&#xff1b;可以随时添加和删除列表元素&#xff1b;可以包含不同数据类型 使用 【】 定义列表&#xff1b;元素之间用 , 分开 my_list [1,love,0.123,[1,2,3]] print(my_list)len() &#xff1a;获取元素个数&#xff1b;空列表…

大数据系列 | 白话讲解大数据技术生态中Hadoop、Hive、Spark的关系介绍

大数据属于数据管理系统的范畴&#xff0c;数据管理系统无非就两个问题&#xff1a;数据怎么存、数据怎么算    现在的信息爆炸时代&#xff0c;一台服务器数据存不下&#xff0c;可以找10台服务器存储&#xff0c;10台存储不下&#xff0c;可以再找100台服务器存储。但是这1…

分布式 IO 模块:港口控制主柜的智能 “助手”

在繁忙的港口&#xff0c;每一个集装箱的装卸、每一艘货轮的停靠与离港&#xff0c;都离不开高效精准的控制系统。港口控制主柜作为整个港口作业的核心枢纽之一&#xff0c;其稳定运行至关重要。而明达技术自主研发推出的MR30分布式 IO 模块可作为从站&#xff0c;与 PLC&#…

Golang GORM系列:GORM 高级查询教程

有效的数据检索是任何程序功能的基础。健壮的Go对象关系映射包&#xff08;称为GORM&#xff09;除了标准的CRUD操作之外&#xff0c;还提供了复杂的查询功能。这是学习如何使用GORM进行高级查询的综合资源。我们将涵盖WHERE条件、连接、关联、预加载相关数据&#xff0c;甚至涉…

常见的数据仓库有哪些?

数据仓库(Data Warehouse,简称数仓)是企业用于存储、管理和分析大量数据的重要工具,其核心目标是通过整合和处理数据,为决策提供高质量、一致性和可信度的数据支持。在构建和使用数仓时,选择合适的工具和技术至关重要。以下是常见的数仓工具及其特点的详细介绍: 1. Hiv…

搜维尔科技在动作捕捉与动画制作、汽车制造与安全测试、机器人与自动化领域的一些案例

动作捕捉与动画制作领域 1.逼真的手部和面部动画制作&#xff1a;动画师施先生利用搜维尔科技代理的Xsens套装、Manus VR手套和Faceware的面部动作捕捉系统&#xff0c;捕捉短片中人物的手部和面部动作&#xff0c;再将数据重新定位到角色骨架上并调整&#xff0c;最终在虚幻引…

HTTP3原理解析和实战应用

http协议原理解析 HTTP1.1改动 keeplive 在http1.0版本中http连接会在每次请求都会发起连接, 并且每次连接在保证安全性都需要建立三次握手, 每次请求后就立即断开连接, 下次请求就还需要重新建立连接.这样就提升了请求的复杂度. keeplive就使得每次建立连接后可以多次请求…

【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法

文章目录 一、互斥问题及分布式系统的特性二、分布式互斥算法1. 集中互斥算法调用流程优缺点 2. 基于许可的互斥算法&#xff08;Lamport 算法&#xff09;调用流程优缺点 3. 令牌环互斥算法调用流程优缺点 三、三种算法对比 在分布式系统中&#xff0c;多个应用服务可能会同时…