【项目-轻量级Web Server lock类】
信号同步机制封装
- Lock类
- 信号量——sem类
- 初始化信号量sem_init()
- 销毁信号量sem_destory()
- 对信号量进行P操作sem_wait()
- 对信号进行V操作sem_post()
- 互斥锁——locker类
- 初始化互斥量pthread_mutex_init()
- 销毁互斥量pthread_mutex_destroy()
- 给互斥锁加锁pthread_mutex_lock()
- 解锁互斥量pthread_mutex_unlock()
- 条件变量——cond类
- 初始化条件变量pthread_cond_init()
- 销毁条件变量对象pthread_cond_destory()
- 唤醒线程pthread_cond_broadcast()
- 阻塞线程pthread_cond_wait()
- 发送信号通知线程pthread_cond_signal()
Lock类
信号量——sem类
信号量是一种特殊的变量,它只能取自然数并且只支持两种操作,P(wait)和V(signal)
-
P 操作会使得信号量的值减 1,如果此时信号量的值小于 0,则调用进程或线程会被阻塞,等待其他进程或线程对信号量进行 V 操作,使得信号量的值大于 0,此时阻塞的进程或线程才能继续执行
-
V 操作会使得信号量的值加 1,如果此时信号量的值小于等于 0,则会唤醒阻塞在该信号量上的某个进程或线程
信号量的取值可以是任何自然数,根据初始值的不同可以分为两类:
-
二进制信号量:指初始值为 1 的信号量,此类信号量只有 1 和 0 两个值,通常用来替代互斥锁实现线程同步
-
计数信号量:指初始值大于 1 的信号量,当进程中存在多个线程,但某公共资源允许同时访问的线程数量是有限的,这时就可以用计数信号量来限制同时访问资源的线程数量
根据使用场景的不同,信号量也可以分为两类:
- 无名信号量:也被称作基于内存的信号量,只可以在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步
- 命名信号量:通常用于不共享内存的情况下,比如进程间通信
在本项目中主要实现的是线程同步,只需要使用无名信号量,主要使用以下几个函数
初始化信号量sem_init()
include <semaphore.h>
int sem_init(sem_t *sem,int pshared,unsignedint value) //初始化一个信号量sem:指向要初始化的信号量的指针
pshared:指定信号量的共享方式。如果值为 0,则信号量将在进程内部共享。如果值为非 0,则信号量可以在不同进程之间共享,需要使用共享内存
value:指定信号量的初值
return:成功则返回0,否则返回-1
销毁信号量sem_destory()
include <semaphore.h>
int sem_destroy(sem_t *sem) //销毁一个信号量sem:指向要销毁的信号量的指针
return:成功返回0,否则返回-1
对信号量进行P操作sem_wait()
include <semaphore.h>
int sem_wait(sem_t *sem) //对信号量进行 P 操作,如果信号量的值小于等于 0,则会阻塞当前线程sem:指向要操作的信号量的指针
return:成功返回0,否则返回-1
对信号进行V操作sem_post()
include <semaphore.h>
int sem_post(sem_t *sem) //对信号量进行 V 操作,如果信号量的值小于等于 0,则会唤醒阻塞在该信号量上的某个线程sem:指向要操作的信号量的指针
return:成功返回0,否则返回-1
互斥锁——locker类
互斥锁,也称互斥量,可以保护关键代码段,以确保独占式访问.当进入关键代码段,获得互斥锁将其加锁;离开关键代码段,唤醒等待该互斥锁的线程
互斥量是一种用于保护临界区的同步机制,可以确保同一时刻只有一个线程访问共享资源。当一个线程访问共享资源时,需要先获取互斥量的锁,其他线程需要等待该锁释放才能继续执行
互斥量不是为了消除竞争,实际上,资源还是共享的,线程间也还是竞争的,只不过通过这种“锁”机制就将共享资源的访问变成互斥操作,也就是说一个线程操作这个资源时,其它线程无法操作它,从而消除与时间有关的错误。但是,这种锁机制不是强制的,互斥锁实质上是操作系统提供的一把“建议锁”(又称“协同锁”),建议程序中有多线程访问共享资源的时候使用该机制
因此,即使有了mutex,其它线程如果不按照这种锁机制来访问共享数据的话,依然会造成数据混乱。所以为了避免这种情况,所有访问该共享资源的线程必须采用相同的锁机制
初始化互斥量pthread_mutex_init()
include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) //初始化互斥量mutex:指向要初始化的互斥量的指针
attr:指向互斥量属性对象的指针,通常设置为 NULL
return:成功则返回0,否则返回一个正整数的错误码
销毁互斥量pthread_mutex_destroy()
include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex) //销毁互斥量mutex:指向要销毁的互斥量的指针
return:成功则返回0,否则返回一个正整数的错误码
给互斥锁加锁pthread_mutex_lock()
include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex) //给互斥量加锁,如果互斥量已经被锁住,则阻塞当前线程,直到互斥量被解锁mutex:指向要加锁的互斥量的指针
return:成功则返回0,否则返回一个正整数的错误码
解锁互斥量pthread_mutex_unlock()
include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex) //解锁互斥量,如果有等待该互斥量的线程,则唤醒其中的一个线程mutex:指向要加锁的互斥量的指针
return:成功则返回0,否则返回一个正整数的错误码
条件变量——cond类
条件变量提供了一种线程间的通知机制,当某个共享数据达到某个值时,唤醒等待这个共享数据的线程
条件变量利用线程间共享的全局变量进行同步,主要包括两个动作:一个线程等待条件变量的条件成立而挂起;另一个线程使条件成立(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥量结合在一起
初始化条件变量pthread_cond_init()
include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) //初始化条件变量对象,设置相关属性cond:指向条件变量对象的指针
attr:指向线程条件属性对象的指针。一般为 NULL
return:成功则返回0,失败返回错误号
销毁条件变量对象pthread_cond_destory()
include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond) //销毁条件变量对象,释放资源cond:指向条件变量对象的指针
return:成功则返回0,失败返回错误号
唤醒线程pthread_cond_broadcast()
函数以广播的方式唤醒所有等待目标条件变量的线程
include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond) //唤醒所有在条件变量上等待的线程cond:指向条件变量对象的指针
return:成功则返回0,失败返回错误号
阻塞线程pthread_cond_wait()
函数执行时,先把调用线程放入条件变量的请求队列,然后将互斥锁mutex解锁,当函数成功返回为0时,互斥锁会再次被锁上. 也就是说函数内部会有一次解锁和加锁操作
include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) //让当前线程阻塞在条件变量上等待唤醒cond:指向条件变量对象的指针
mutex:指向互斥锁对象的指针,用于保护条件变量
return:成功则返回0,失败返回错误号
发送信号通知线程pthread_cond_signal()
pthread_cond_signal 只会通知一个等待该条件变量的线程,如果有多个线程在等待,则只有一个线程会收到通知,其余线程还会继续等待,直到下一次收到信号
必须在已经获得与条件变量相关的互斥锁之后才能调用该函数
如果没有等待该条件变量的线程,调用该函数也不会产生任何作用
include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond)cond:指向条件变量的指针
return:成功则返回0,失败返回错误号
锁机制的功能
锁机制用来实现多线程同步,通过锁机制,确保任一时刻只能有一个线程能进入关键代码段
为便于实现同步类的RAII机制(“Resource Acquisition is Initialization”直译过来是“资源获取即初始化”),该项目在pthread库的基础上进行了封装,实现了类似于C++11的mutex标准库功能
————————————————
源码
/****************locker.h*******************/
#ifndef LOCKER_H
#define LOCKER_H#include <exception>
#include <semaphore.h>
#include <pthread.h>class sem {
public:sem(int value = 0) {if (sem_init(&m_sem, 0, value) != 0) {throw std::exception();}}~sem() {sem_destroy(&m_sem);}bool wait() {return sem_wait(&m_sem) == 0;}bool post() {return sem_post(&m_sem) == 0;}
private:sem_t m_sem;
};class locker {
public:locker() {if (pthread_mutex_init(&m_mutex, NULL) != 0) {throw std::exception();}}~locker() {pthread_mutex_destroy(&m_mutex);}bool lock() {return pthread_mutex_lock(&m_mutex);}bool unlock() {return pthread_mutex_unlock(&m_mutex);}pthread_mutex_t* get() {return &m_mutex;}
private:pthread_mutex_t m_mutex;
};class cond {
public:cond() {if (pthread_cond_init(&m_cond, NULL) != 0) {throw std::exception();}}~cond() {pthread_cond_destroy(&m_cond);}bool wait(pthread_mutex_t* m_mutex) {int ret = pthread_cond_wait(&m_cond, m_mutex);return ret == 0;}bool timewait(pthread_mutex_t* m_mutex, struct timespec t) {return pthread_cond_timedwait(&m_cond, m_mutex, &t);}bool signal() {return pthread_cond_signal(&m_cond) == 0;}bool broadcast() {return pthread_cond_broadcast(&m_cond) == 0;}
private:pthread_cond_t m_cond;
};#endif/*测试locker类代码
// 生产者线程函数
void* producer(void* arg) {block_queue<int>* queue = static_cast<block_queue<int>*>(arg);for (int item = 0; item < 20; item++) {queue->push(item);LOG_INFO("生产者产生数据i = %d", item);usleep((rand() % 5 + 1) * 50000);}return nullptr;
}// 消费者线程函数
void* consumer(void* arg) {block_queue<int>* queue = static_cast<block_queue<int>*>(arg);for (int item = 0; item < 20; item++) {queue->pop(item);LOG_INFO("消费者处理数据i = %d", item);}return nullptr;
}int main() {block_queue<int> queue;pthread_t tid_prod, tid_cons;pthread_create(&tid_prod, nullptr, producer, &queue);pthread_create(&tid_cons, nullptr, consumer, &queue);pthread_join(tid_prod, nullptr);pthread_join(tid_cons, nullptr);return 0;
}
*/
相关文章:
【项目-轻量级Web Server lock类】
信号同步机制封装 Lock类信号量——sem类初始化信号量sem_init()销毁信号量sem_destory()对信号量进行P操作sem_wait()对信号进行V操作sem_post() 互斥锁——locker类初始化互斥量pthread_mutex_init()销毁互斥量pthread_mutex_destroy()给互斥锁加锁pthread_mutex_lock()解锁互…...
数据分析_计划
我做大数据的有6年了,以前都是用sql,或者spark,java,scala,python去做。现在这些平台搭建、维护、大多数都是搭建一次就完了,而且维护大多是大厂直接用云平台去做。ETL也是就做一次就够了,我们公…...

LDAPWordlistHarvester:基于LDAP数据的字典生成工具
关于LDAPWordlistHarvester LDAPWordlistHarvester是一款功能强大的字典列表生成工具,该工具可以根据LDAP中的详细信息生成字典列表文件,广大研究人员随后可以利用生成的字典文件测试目标域账号的非随机密码安全性。 工具特征 1、支持根据LDAP中的详细信…...

dhtmlx-gantt甘特图数据展示
官网文档:甘特图文档 实现效果: 首先需要下载 dhtmlx-gantt组件 npm i dhtmlx-gantt //我项目中使用的是"dhtmlx-gantt": "^8.0.6" 这个版本,不同的版本api或是文档中存在的方法稍有差异 界面引用 <template>&l…...

《云原生安全攻防》-- 容器攻击案例:Docker容器逃逸
当攻击者获得一个容器环境的shell权限时,攻击者往往会尝试进行容器逃逸,利用容器环境中的错误配置或是漏洞问题,从容器成功逃逸到宿主机,从而获取到更高的访问权限。 在本节课程中,我们将详细介绍一些常见的容器逃逸方…...
初学者指南:如何搭建和配置 Nginx 服务器
初学者指南:如何搭建和配置 Nginx 服务器 Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。本文将详细介绍如何在 Linux 上安装、配置和管理 Nginx 服务器。 一、安装 Nginx Nginx 可以安装在多种操作系统上&#x…...

[AHK] WinHttpRequest.5.1报错 0x80092004 找不到对象或属性
目录 背景描述 用浏览器访问,正常返回 编辑 AHK v2官方示例源代码 AHK v2运行结果报错(0x80092004) 找不到对象或属性 用thqby大佬的WinHttpRequest.ahk库测试报错 0x80092004 找不到对象或属性 附: 用Apifox访问,也正常返回 AHK v1 …...
`speech_recognition` 是一个流行的库
在Python中,speech_recognition 是一个流行的库,用于从各种来源(如麦克风、文件等)进行语音识别。以下是您提到的技术名称和相应的Python代码示例。 技术名称 语音识别(Speech Recognition):这…...

MFC Ribbon菜单 - 中英文实时切换方法
简介 最近在搞一个老外的项目,本来谈的好好的,纯英文界面。项目接近尾声了,又提出了中英文实时切换的新需求,没办法就只能想办法,毕竟客户最大嘛。 实现方法 还好本来的ribbon英文菜单不复杂,就用纯C编码…...

MFC程序创建word,创建表格,写入数据
文章目录 1、MFC程序功能:2、MFC程序实现2.1 创建项目2.2 添加word操作类2.3 添加word资源2.4 编写代码,实现将数据写入到word2.5 运行程序、验证功能3、工程代码下载 1、MFC程序功能: 创建word文档;向文档中写入字符串ÿ…...

FPGA:基于复旦微FMQL10S400 /FMQL20S400 国产化核心板
复旦微电子是国内集成电路设计行业的领军企业之一,早在2000年就在香港创业板上市,成为行业内首家上市公司。公司的RFID芯片、智能卡芯片、EEPROM、智能电表MCU等多种产品在市场上的占有率位居行业前列。 今天介绍的是搭载复旦微 FMQL10S400/FMQL20S400的…...

centos下使用yum安装keepalived工具
1、安装如下rpm包,不安装此包在装keepalived时会报错 mkdir keepalived_rpm cd keepalived_rpm/ wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-community-libs-compat-8.0.36-1.el7.x86_64.rpm 2、使用yum进行keepalived的安装 yum -y install keepal…...

无人机图像目标检测
本仓库是人工智能课程的课程作业仓库,主要是完成无人机图像目标检测的任务,我们对visdrone数据集进行了处理,在yolo和ssd两种框架下进行了训练和测试,并编写demo用于实时的无人机图像目标检测。 requirements依赖: ss…...
JSqlParser 解析 sql
目录 前言一、Maven依赖二、获取sql中的表名三、获取sql中的具体信息 前言 JSqlParser是一个 SQL 语句解析器。它将 SQL 语句转换为可遍历的 Java 类层次结构,可以方便的用代码对 SQL 语句进行解析,修改等操作。 官网 api 文档和 github 地址如下&…...

Vue中使用mind-map实现在线思维导图
概述 在前面的文章Vue中实现在线画流程图实现中介绍了流程图的在线绘制,在本文,给大家分享一下基于mind-map实现在线的思维导图,并实现:1. 导图导出为图片;2. 打开xmind文件。 实现效果 实现 1. mind-map简介 simp…...

ChatGPT 深度解析:技术驱动的智能对话
在当今科技飞速发展的时代,ChatGPT 无疑成为了最耀眼的明星之一。它以其令人惊叹的智能对话能力,引发了全球范围内的广泛关注和热议。 ChatGPT 背后的技术堪称精妙绝伦。它基于深度学习算法,通过对海量数据的学习和分析,从而能够理…...

Armv8-R内存模型详解
目录 1.内存模型的必要性 2.Armv8-R内存模型分类 2.1 Normal memory 2.2 Device Memory 2.2.1 Gathering 2.2.2 Reordering 2.2.3 Early Write Acknowledgement 3.小结 大家好,今天是悲伤的肌肉。 在调研区域控制器芯片时,发现了S32Z、Stellar …...
Python面经
文章目录 Python基本概念1. Python是**解释型**语言还是**编译型**语言2. Python是**面向对象**语言还是面向过程语言3. Python基本数据类型4.append和 extend区别5.del、pop和remove区别6. sort和sorted区别介绍一下Python 中的字符串编码is 和 的区别*arg 和**kwarg作用浅拷…...

海外ASO:iOS与谷歌优化的相同点和区别
海外ASO是针对iOS的App Store和谷歌的Google Play这两个主要海外应用商店进行的优化过程,两个不同的平台需要采取不同的优化策略,以下是对iOS优化和谷歌优化的详细解析: 一、iOS优化(App Store) 1、关键词覆盖 选择关…...

【C++题解】1168. 歌唱比赛评分
问题:1168. 歌唱比赛评分 类型:数组找数 题目描述: 四(1) 班要举行一次歌唱比赛,以选拔更好的苗子参加校的歌唱比赛。评分办法如下:设 N 个评委,打 N 个分数( 0≤每个分…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...