TinyWebServer项目笔记——01 线程同步机制封装类

目录

1.基础知识

(1)RALL

(2)信号量

(3)互斥量

(4)条件变量

2.功能


1.基础知识

(1)RALL

        RALL全称“Resource Acquisition is Initialization”,翻译过来就是“资源获取即初始化”。用于管理资源的生命周期。RALL的核心思想是将资源的获取与对象的初始化绑定在一起,资源的释放与对象的析构绑定在一起。通过这种方式,确保资源在使用完毕后被正确释放,避免资源泄漏。

RALL的工作原理

        1.资源获取即初始化——在对象的构造函数中获取资源(如内存、文件句柄、锁等)。

        2.资源释放即析构——在对象的析构函数中释放资源。

        由于C++的机制,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。

RALL的优点

        1.避免资源泄漏:资源在析构时自动释放,无需手动管理。

        2.异常安全:即使在代码中发生异常,资源也会被正确释放。

        3.代码简洁:不需要显式释放资源,减少代码的复杂性。

RALL的典型应用

        1.智能指针。2.文件句柄管理。3.锁管理。

(2)信号量

        信号量是一种用于控制多个线程或进程对共享资源访问的同步机制。主要用于解决并发编程中的同步问题。信号量的核心是一个整数计数器,用于表示可用资源的数量。通过两个原子操作(wait和signal)来管理资源的分配和释放。

信号量的基本操作

        1.wait(或p操作)

        如果信号量的值大于0,则将其减1,表示资源被占用。

        如果信号量的值为0,则线程或进程会被阻塞,直到信号量的值大于0。

        2.signal(或v操作)

        将信号量的值加1,表示资源被释放。

        如果有线程或进程正在等待该信号量,则唤醒其中一个。

信号量的类型

        1.二进制信号量。信号量的值只能是0或1。类似于互斥锁,用于实现互斥访问。

        2.计数信号量:信号量的值可以是任意非负整数。用于控制对多个资源的访问。

 信号量的应用场景

        1.资源池管理:例如数据库连接池、线程池等。信号量可以限制同时使用的资源数量。

        2.生成者-消费者模型:信号量可以用于同步生产者和消费者线程,确保缓冲区不会溢出或下溢。

        3.读写锁:信号量可以实现读写锁,允许多个读线程同时访问资源,但只允许一个写线程访问。

注意事项

        1.死锁:信号量使用不当可能会导致死锁。

        2.性能开销:信号量的实现依赖操作系统内核,频繁调用会带来额外的开销。

(3)互斥量

        互斥量是一种用于多线程编程的同步机制,用于保护共享资源,防止多个线程同时访问或修改这些资源。从而避免数据竞争和不一致问题,

        互斥量的核心思想是:当一个线程持有互斥量时,其他线程必须等待,直到该线程释放互斥量后才能继续访问共享资源。

互斥量的基本操作

        1.加锁:线程尝试获取互斥量的所有权。如果互斥量已被其他线程持有,则当前线程会被阻塞,直到互斥量被释放。

        2.解锁:线程释放互斥量的所有权。其他等待的线程可以尝试获取互斥量。

互斥量的特性

        1.互斥性:同一时刻只能有一个线程可以持有互斥量。

        2.所有权:只有加锁的线程才能解锁互斥量。

        3.阻塞机制:如果互斥量被其他线程持有,尝试加锁的线程会被阻塞,直到互斥量被释放。

互斥量的应用场景

        1.保护共享数据。2.实现线程安全的单例模式。3.同步多个线程的操作。

互斥量的注意事项

        1.死锁:如果多个线程互相等待对方释放锁,可能会导致死锁。

        避免死锁的方法包括:按固定顺序加锁,使用lock一次性加锁多个互斥量。

        2.性能开销:互斥量的加锁和解锁操作会带来额外的性能开销,尤其在高并发场景下。

        3.锁粒度:锁的粒度应尽可能小,以减少线程阻塞的时间。

(4)条件变量

        条件变量是一种用于多线程编程的同步机制,通常与互斥量结合使用。用于实现线程间的等待与通知机制。条件变量的核心作用是允许线程在某些条件不满足时进入等待状态,并在条件满足时被唤醒。

条件变量的基本操作

        1.wait:线程调用wait时会释放互斥量,并进入等待状态。当其他线程调用notify_one或notify_all时,等待的线程会被唤醒,重新获得互斥量。

        2.notify_one:唤醒一个正在等待的线程。

        3.notify_all:唤醒所有正在等待的线程。

典型应用场景

        1.生产者-消费者模型:当缓冲区为空时,消费者线程等待,当缓冲区有数据时,生产者线程通知消费者线程。当缓存区满时,生产者线程等待,当缓冲区有空闲时,通知生产者。

        2.任务队列:当任务队列为空时,工作线程等待,当任务队列不为空时,通知工作线程。

        3.事件驱动编程:线程等待某个事件发生,事件发生后通知等待的线程。

注意事项

        1.虚假唤醒:即没有调用notify_one或notify_all,等待的线程也可能被唤醒。可以在wait中使用条件判断(Lambda表达式)检查条件是否真正满足。

        2.死锁:条件变量使用不当,可能会导致死锁。

        3.性能开销:条件变量的操作涉及系统调用,可能会带来额外的性能开销。

2.功能

        封装的功能

        类中主要对Linux下的三种锁进行封装,将锁的创建与销毁函数封装在类的构造和析构函数中,实现RALL机制。例如

class sem{
     public:
         //构造函数
         sem()
         {
             //信号量初始化
             if(sem_init(&m_sem,0,0)!=0){
                throw std::exception();
           }
        }
        //析构函数
        ~sem()
        {
            //信号量销毁
           sem_destroy(&m_sem);
       }
    private:
       sem_t m_sem;
};

        将重复的代码封装成函数,减少重复。

 1   //条件变量的使用机制需要配合锁来使用
 2   //内部会有一次加锁和解锁
 3   //封装起来会使得更加简洁
 4   bool wait()
 5   {
 6       int ret=0;
 7       pthread_mutex_lock(&m_mutex);
 8       ret=pthread_cond_wait(&m_cond,&m_mutex);
 9       pthread_mutex_unlock(&m_mutex);
10       return ret==0;
11   }
12   bool signal()
13   {
14       return pthread_cond_signal(&m_cond)==0;
15   }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openharmory-鸿蒙生态设备之间文件互传发现、接入认证和文件传输

软件版本 OpenHarmony系统版本基线:基于 OpenHarmony-v5.0.0-Release。 图库应用版本:基于OpenHarmony-v5.0.0-Release。 文件管理器应用版本:基于OpenHarmony-v5.0.0-Release。 7 用户历程图 8 设备发现 8.1 设备交互流程图 8.2 设备发…

Linux系统编程--线程同步

目录 一、前言 二、线程饥饿 三、线程同步 四、条件变量 1、cond 2、条件变量的使用 五、条件变量与互斥锁 一、前言 上篇文章我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实…

【HarmonyOS Next】鸿蒙加固方案调研和分析

【HarmonyOS Next】鸿蒙加固方案调研和分析 一、前言 根据鸿蒙应用的上架流程,本地构建app文件后,上架到AGC平台,平台会进行解析。根据鸿蒙系统的特殊设置,仿照IOS的生态闭环方案。只能从AGC应用市场下载app进行安装。这样的流程…

# 深入理解RNN(一):循环神经网络的核心计算机制

深入理解RNN:循环神经网络的核心计算机制 RNN示意图 引言 在自然语言处理、时间序列预测、语音识别等涉及序列数据的领域,循环神经网络(RNN)一直扮演着核心角色。尽管近年来Transformer等架构逐渐成为主流,RNN的基本原理和思想依然对于理…

深度学习实战车道线检测

深度学习实战车道线检测 这里写目录标题 车道线原理整体架构设计核心原理步骤1. 特征提取(骨干网络)2. 特征融合3. 车道线表示与分类4. 损失函数5. 后处理 速度优势的来源 软件实现安装环境与文件说明实验测试 结束语 车道线原理 Lane - Detection是一种…

【redis】五种数据类型和编码方式

文章目录 五种数据类型编码方式stringhashlistsetzset查询内部编码 五种数据类型 字符串:Java 中的 String哈希:Java 中的 HashMap列表:Java 中的 List集合:Java 中的 Set有序集合:除了存 member 之外,还有…

Next.js Server Action 提交 vs 前端 Fetch 提交:核心区别与优劣分析

在使用 Next.js 开发时,开发者经常会面临一个问题:前端的数据提交应该直接 Fetch 调用 API 还是使用 Next.js 提供的 Server Action 提交? 本文将深度解析: ✅ Server Action 提交数据的工作原理✅ 前端 Fetch 提交数据的优缺点…

DeepSeek开启AI办公新模式,WPS/Office集成DeepSeek-R1本地大模型!

从央视到地方媒体,已有多家媒体机构推出AI主播,最近杭州文化广播电视集团的《杭州新闻联播》节目,使用AI主持人进行新闻播报,且做到了0失误率,可见AI正在逐渐取代部分行业和一些重复性的工作,这一现象引发很…

混合存储HDD+SSD机型磁盘阵列,配上SSD缓存功能,性能提升300%

企业日常运行各种文件无处不在,文档、报告、视频、应用数据......面对成千上万的文件,团队之间需要做到无障碍协作,员工能够即时快速访问、共享处理文件。随着业务增长,数字化办公不仅需要大容量,快速高效的文件访问越…

【AI】什么是Embedding向量模型?我们应该如何选择?

我们之前讲的搭建本地知识库,基本都是使用检索增强生成(RAG)技术来搭建,Embedding模型则是RAG的核心,同时也是大模型落地必不可少的技术。那么今天我们就来聊聊Embedding向量模型: 一、Embedding模型是什么? Embedding模型是一种将离散数据(如文本、图像、用户行为等)…

Java在小米SU7 Ultra汽车中的技术赋能

目录 一、智能驾驶“大脑”与实时数据 场景一:海量数据的分布式计算 场景二:实时决策的毫秒级响应 场景三:弹性扩展与容错机制 技术隐喻: 二、车载信息系统(IVI)的交互 场景一:Android Automo…

【Python 数据结构 8.串】

目录 一、串的基本概念 1.串的概念 2.获取串的长度 3.串的拷贝 4.串的比较 5.串的拼接 6.串的索引 二、Python中串的使用 1.串的定义 2.串的拼接 3.获取串的长度 4.获取子串位置 5.获取字符串的索引 6.字符串的切片 7.字符串反转 8.字符串的比较 9.字符串的赋值 三、实战 1.344…

计算机视觉cv2入门之图像的读取,显示,与保存

在计算机视觉领域,Python的cv2库是一个不可或缺的工具,它提供了丰富的图像处理功能。作为OpenCV的Python接口,cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV 图像格式 BMP格式 …

LLM 学习(二 完结 Multi-Head Attention、Encoder、Decoder)

文章目录 LLM 学习(二 完结 Multi-Head Attention、Encoder、Decoder)Self-Attention (自注意力机制)结构多头注意力 EncoderAdd & Norm 层Feed Forward 层 EncoderDecoder的第一个Multi-Head AttentionMasked 操作Teacher Fo…

006-获取硬件序列号

获取硬件序列号 我将从跨平台角度系统讲解如何通过C获取硬件序列号的核心技术&#xff0c;并提供可移植性代码实现。 一、处理器序列号获取 Windows平台 #include <windows.h> #include <intrin.h>std::string GetCPUSerial_Win() {DWORD cpuInfo[2] { 0 };__c…

GDB调试技巧:多线程案例分析(保姆级)

在软件开发的复杂世界里&#xff0c;高效的调试工具是解决问题的关键利器。今天&#xff0c;我们将深入探讨强大的调试工具 ——GDB&#xff08;GNU Debugger&#xff09;。GDB 为开发者提供了一种深入程序内部运行机制、查找错误和优化性能的有效途径。让我们一同开启 GDB 的调…

OSPF的各种LSA类型,多区域及特殊区域

一、OSPF的LSA类型 OSPF&#xff08;开放最短路径优先&#xff09;协议使用多种LSA&#xff08;链路状态通告&#xff09;类型来交换网络拓扑信息。以下是主要LSA类型的详细分类及其作用&#xff1a; 1. Type 1 LSA&#xff08;路由器LSA Router LSA&#xff09; 生成者&…

JavaScript系列06-深入理解 JavaScript 事件系统:从原生事件到 React 合成事件

JavaScript 事件系统是构建交互式 Web 应用的核心。本文从原生 DOM 事件到 React 的合成事件&#xff0c;内容涵盖&#xff1a; JavaScript 事件基础&#xff1a;事件类型、事件注册、事件对象事件传播机制&#xff1a;捕获、目标和冒泡阶段高级事件技术&#xff1a;事件委托、…

字节跳动C++客户端开发实习生内推-抖音基础技术

智能手机爱好者和使用者&#xff0c;追求良好的用户体验&#xff1b; 具有良好的编程习惯&#xff0c;代码结构清晰&#xff0c;命名规范&#xff1b; 熟练掌握数据结构与算法、计算机网络、操作系统、编译原理等课程&#xff1b; 熟练掌握C/C/OC/Swift一种或多种语言&#xff…

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…