【Linux篇】高并发编程终极指南:线程池优化、单例模式陷阱与死锁避坑实战
深入理解线程池设计与应用:高效并发编程的秘密
- 一. 线程池
- 1.1 什么是线程池
- 1.2 线程池的优点
- 1.3 线程池的应用场景
- 二. 线程池设计
- 三. 单例模式
- 3.1 什么是单例模式
- 3.2 单例模式特点
- 3.3 实现单例模式方法
- 3.3.1 饿汉实现⽅式
- 3.3.2 懒汉实现⽅式
- 四. 线程安全和重入问题
- 4.1 线程安全
- 4.1.1 什么是线程安全?
- 4.2 重入
- 4.2.1 什么是重入?
- 五. 死锁
- 5.1 基本概念
- 5.2 死锁必要条件
- 5.3 如何避免死锁
- 6. STL,智能指针与线程安全的关系
- 6.1 STL中的容器是否是线程安全的?
- 6.2 智能指针是否是线程安全的?
- 七. 最后
一. 线程池
1.1 什么是线程池
线程池(Thread Pool)是一种多线程管理技术,用于提高程序中多线程的执行效率和资源利用率。
具体来说,线程池在程序启动时预先创建一定数量的线程,这些线程处于空闲等待状态。当有任务到来时,线程池从空闲线程中分配一个线程来执行任务,执行完后线程不会被销毁,而是继续回到线程池中等待下一次任务。这样避免了频繁创建和销毁线程带来的性能开销。
可能大家又会有这样的疑问:线程池为啥提高效率,他提前创建一定数量的线程池操作系统要维护它这不是要花费一定的成本吗?
-
避免频繁创建和销毁线程的开销:创建和销毁线程是一个比较耗时且资源消耗大的操作,包括分配栈空间、初始化线程上下文、内核调度等。应用线程池后,线程可以被重复利用,免去了频繁创建和销毁的成本。
-
控制并发线程数量,避免资源过载:线程池固定线程数量,防止大量线程同时运行导致CPU调度压力加大、内存耗尽、上下文切换频繁,从而反而降低性能。
-
减少线程切换开销:线程池里线程数量有限,可以减少操作系统频繁进行线程切换的次数(上下文切换是昂贵的),从而提升CPU利用率和执行效率。
-
快速响应新任务:因为线程已经准备好,任务到达时可以马上被线程执行,无需等待创建线程,提升系统响应速度。
总结:线程池的维护成本是固定且有限的,而节省的线程创建销毁开销及调度管理开销通常远大于维护成本,最终整体提升了系统的性能和效率。
1.2 线程池的优点
线程池的主要优点包括:
-
降低线程创建和销毁的系统开销
-
控制最大并发线程数,防止资源过度消耗
-
提高任务执行的响应速度
-
便于管理和调优多线程环境
1.3 线程池的应用场景
- 高并发服务器
例如Web服务器、数据库服务器、文件服务器等,需要同时处理大量客户端请求,通过线程池复用线程,减少线程创建销毁开销,提高响应速度和吞吐量。
- 异步任务处理
后台任务处理、日志写入、消息队列消费等场景,线程池可以异步执行任务,提高主线程的响应性能,避免阻塞。
- 定时任务调度
定时执行周期性任务时,使用线程池管理执行线程,保证资源利用率和任务调度的稳定性。
二. 线程池设计
想一想在设计线程池之前,我们需要什么变量。
- vector:线程池固定数量线程集合
- _num:线程个数
- queue:任务队列,存放提交的任务
- _cond:条件变量,用于线程等待和唤醒
- _mutex:互斥锁,保护任务队列和状态的同步访问
- _isrunning:线程池运行状态标志,false时停止线程
- _sleepernum:当前处于等待状态(休眠)的线程数量,用于判断是否要唤醒休眠的线程去处理任务
通过上述思考可以得到如下的伪代码:
template <typename T>class ThreadPool{private:std::vector<Thread> _threads; // 插入的lamada表达式会构建Thread类对象int _num; // 线程池中的线程个数std::queue<T> _taskq;Cond _cond;Mutex _mutex;bool _isrunning;int _sleepernum;};
接下来需要创建线程池对象,创建一定数量的线程,并将该线程需要的函数传给指定的线程。而构造函数就可以完成该功能,为了支持泛型编程,我们设计成模版。伪代码如下:
static const int gnum = 5;
template <typename T>
class ThreadPool
{
private:
ThreadPool(int num = gnum): _num(num),_isrunning(false),//线程还未启动_sleepernum(0)//线程休眠个数{for (int i = 0; i < num; i++){_threads.emplace_back([this](){HandlerTask();});}}
};
该构造函数在创建thread对象的时候,还会将HandlerTask()函数赋值至自己的成员变量_func中,完成回调功能。
清理资源,做任何事有始有终。析构函数完成该功能。伪代码如下:
template <typename T>
class ThreadPool
{
public:~ThreadPool(){}
};
往任务队列入任务,如何入任务,已经启动的线程才给他入任务,没有启动的线程给它入任务干嘛,他又不做事,为了保持原子性防止一个任务被多个线程执行,咱们直接加锁,如果线程都在休眠,需要手动唤醒一个线程去处理任务,通过上述思考,得到的伪代码如下:
template <typename T>
class ThreadPool
{
public:bool Equeue(const T &in){if (_isrunning){LockGuard lockguard(_mutex);_taskq.push(in);if (_threads.size() == _sleepernum)WakeUpOne();return true;}return false;}
};
如何启动线程池,将所有线程对象调用pthread_create(),创建线程,建立虚拟地址空间的映射,启动线程前,需要将_isrunning的状态修改为true,因为默认是false,这会影响回调函数处理任务的逻辑,伪代码如下:
template <typename T>
class ThreadPool
{
public:void Start(){if (_isrunning)return; // 线程已启动直接返回即可_isrunning = true; // 不可省略,会导致任务不会被处理for (auto &thread : _threads){thread.Start();LOG(LogLevel::INFO) << "start new thread success:" << thread.Name();}}
};
停止及等待线程池,伪代码如下,直接调用接口就行,特别需要注意,在停止所有线程前,需将_isrunning的状态设置为false,方便回调函数将该线程从while跳出,唤醒所有休眠的线程,直接同样的逻辑,伪代码如下:
void Stop(){if (!_isrunning)return;_isrunning = false;// 唤醒所有休眠的线程WakeUpAllThread();}void Join(){for (auto &thread : _threads){thread.Join();}}
唤醒一个和所有休眠线程,直接调用接口即可,伪代码如下:
void WakeUpAllThread(){LockGuard lockguard(_mutex);if (_sleepernum > 0)_cond.Broadcast();LOG(LogLevel::INFO) << "唤醒所有的休眠线程";}void WakeUpOne(){_cond.Signal();LOG(LogLevel::INFO) << "唤醒一个的休眠线程";}
线程池中的线程执行HandlerTask()函数,伪代码如下:
template <typename T>
class ThreadPool
{
public:void HandlerTask(){char name[128];pthread_getname_np(pthread_self(), name, sizeof(name));while (true){T t;{LockGuard lockguard(_mutex);while (_taskq.empty() && _isrunning){_sleepernum++;_cond.Wait(_mutex);_sleepernum--;}// 内部线程被唤醒if (!_isrunning && _taskq.empty()){LOG(LogLevel::INFO) << name << " 退出了,线程池退出&&任务队列为空";break;}// 一定有任务t = _taskq.front();_taskq.pop();}t(); // 任务已经是私有的,不需要加锁}}
};
- 问题1:while循环条件的必要性???
当线程正在运行且任务队列为空,就需要在条件变量下进行阻塞等待。 - 问题2:如何退出循环???如何理解
当任务队列为空且线程的状态为退出的时候,即可退出循环。 - 问题3:理一下处理任务逻辑
当前线程正在运行,同时任务队列不为空时,才让线程去处理任务。 - 问题4:锁的必要性???
为了保持原子性,防止同一任务被多个线程处理。
三. 单例模式
3.1 什么是单例模式
单例模式(Singleton Pattern)是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。单例模式主要解决的是保证在整个应用程序中,某个类只能有一个对象实例,并且该实例可以被全局访问。
3.2 单例模式特点
-
唯一性:确保类只有一个实例,并且提供一个全局访问点。
-
懒加载:单例实例的创建是延迟的,即在第一次使用时才创建实例。
-
全局访问:通过一个静态方法可以访问该单例实例。
3.3 实现单例模式方法
只允许存在一个类对象实例,所以要将类的构造函数私有化,将构造函数和赋值运算符禁用,外部就无法创建该类的对象了。如:
namespace A
{class B{private:B(std::string name):_name(name) {}std::string _name;};
}
我们现在尝试创建对象,如下图看看有什么问题?
从图中可以看出类的外部不允许创建该类的对象。类的内部是可以创建对象的,只需要创建一个指向该类对象的静态指针或者静态对象,在初始化即可,因为外部无法访问该指针,可以提供一个静态的方法获取单例对象的句柄。下面展示两种方法实现该原理:
3.3.1 饿汉实现⽅式
template <typename T>
class EagerSingleton {
private:static T instance; // 静态实例(直接初始化)// 私有化构造函数/析构函数EagerSingleton() = default;~EagerSingleton() = default;public:// 删除拷贝构造和赋值运算符EagerSingleton(const EagerSingleton&) = delete;EagerSingleton& operator=(const EagerSingleton&) = delete;static T& GetInstance() {return instance; // 直接返回已存在的实例}
};// 静态成员变量初始化(需在头文件外或模板特化中定义)
template <typename T>
T EagerSingleton<T>::instance;
当创建该类对象时,直接创建静态实例,不管它需不需要使用,这就是饿汉模式,可以看出该设计模式浪费空间延迟服务启动,所以需要改进,这就出现了懒汉模式。
3.3.2 懒汉实现⽅式
**#include <iostream>
#include <mutex>template <typename T>
class LazySingleton {
private:static T* instance; // 静态指针(不直接创建对象)static std::mutex mtx; // 互斥锁(线程安全)// 私有化构造函数/析构函数LazySingleton() = default;~LazySingleton() = default;public:// 删除拷贝构造和赋值运算符LazySingleton(const LazySingleton&) = delete;LazySingleton& operator=(const LazySingleton&) = delete;static T* GetInstance() {// 双重检查锁定(Double-Checked Locking)if (!instance) {std::lock_guard<std::mutex> lock(mtx);if (!instance) {instance = new T();// 注册析构函数(防止内存泄漏)static std::atexit([] {delete instance;instance = nullptr;});}}return instance;}
};// 静态成员变量初始化(需在头文件外或模板特化中定义)
template <typename T>
T* LazySingleton<T>::instance = nullptr;template <typename T>
std::mutex LazySingleton<T>::mtx;
当需要该类对象才创建对象,可以看出当真正需要时,才创建对象,核心思想就是延时加载,有点类似于动态库的加载,也是不全部加载,当真正需要某些方法时才绑定关联关系。注意:静态成员变量需要在类外部进行初始化。
四. 线程安全和重入问题
4.1 线程安全
4.1.1 什么是线程安全?
线程安全(Thread Safety)是指多个线程同时访问某个代码片段时,程序能够正常运行而不发生异常或错误的现象。换句话说,线程安全是指程序在多线程环境下,即使有多个线程并发执行,仍能保持数据的一致性和正确性。
4.2 重入
4.2.1 什么是重入?
重入(Reentrancy)是指一个方法或代码块在执行过程中可以被同一个线程再次调用,而不会导致冲突或不一致的情况。换句话说,重入是指当一个线程在执行一个方法时,如果该方法在执行过程中再次被相同线程调用,程序能正确处理这种情况,而不会引起死锁、资源冲突或数据错误。
结论:
- 函数是可重⼊的,那就是线程安全的
- 线程安全不⼀定是可重⼊的,⽽可重⼊函数则⼀定是线程安全的。
- 如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重⼊函数若锁还
未释放则会产⽣死锁,因此是不可重⼊的。
五. 死锁
5.1 基本概念
申请一把锁是原子的,但申请两把锁就不是了,因临界资源需要多个锁才能进入,而不同的线程拥有不同的锁,导致两个或多个线程都在等待其它线程释放锁,造成死等待,进而造成死锁。
举个例子:一家棒棒糖超市老板有且仅有一个棒棒糖售价为1元,李四有0.5元,法外狂徒张三也有0.5元,因为棒棒糖为1元,所以两人都不可以买,李四在等张三把他的0.5元给我,法外狂徒张三也在等李四把他的0.5元给我,两人互不相让这就造成任何一个人都不能拿到棒棒糖,进而导致死锁。
如图所示:
5.2 死锁必要条件
- 互斥条件(Mutual Exclusion)互斥条件指的是资源每次只能被一个线程占用。也就是说,如果一个线程正在使用某个资源,其他线程不能使用该资源,直到该线程释放资源。
- 请求和保持条件(Hold and Wait)请求和保持条件是指一个线程至少持有一个资源,并且正在等待其他线程持有的资源。例如:线程A已经持有资源1,并且正在请求资源2;同时线程B已经持有资源2,并请求资源1。这时,两个线程都会处于等待状态,导致死锁。
- 不剥夺条件(No Preemption)不剥夺条件是指一旦资源被线程占有,其他线程无法强行剥夺该资源,只能由持有该资源的线程自行释放。例如:线程A已经获取了资源1并且正在运行,线程B请求资源1时,它必须等待线程A释放该资源,无法强制中断或剥夺资源。
- 循环等待条件(Circular Wait)
循环等待条件指的是,线程集合中存在一个线程等待其他线程持有的资源,并且这种等待关系形成一个闭环(即循环依赖)。例如:线程A等待资源B,线程B等待资源C,线程C等待资源A,形成一个循环。此时,线程们互相等待,无法继续执行,导致死锁。
5.3 如何避免死锁
直接使上述四个条件任意一个条件不成立即可避免死锁。
6. STL,智能指针与线程安全的关系
6.1 STL中的容器是否是线程安全的?
不是,因为STL容器是将性能挖掘到极致,一旦加锁保证线程安全,会对性能造成巨大影响,因此STL默认不是安全的,如果要保证安全,需要调用者自行保证线程安全。
6.2 智能指针是否是线程安全的?
- 对于unique_ptr,由于只是在当前的代码块范围生效,因此不涉及线程安全问题。
- 对于shared_ptr,多个对象需要共用一个引用计数变量,所以存在线程安全问题。标准库基于原子(CAS)方式保证shared_ptr能够高效引用原子计数,来解决该问题。
七. 最后
本文介绍了线程池、单例模式、线程安全、死锁及STL与智能指针的线程安全性。线程池通过复用线程提升性能,适用于高并发和异步任务场景。单例模式确保类唯一实例,提供全局访问,分饿汉和懒汉两种实现。线程安全指多线程下数据一致性,重入是同一线程多次调用不冲突。死锁由互斥、请求保持、不剥夺、循环等待导致,需破坏任一条件避免。STL容器非线程安全,需自行加锁;智能指针中unique_ptr无此问题,shared_ptr通过原子操作保证引用计数安全。关于Linux系统部分的知识就已经全部更新完毕,下一步进入Linux网络部分,踏入新征程。
相关文章:
【Linux篇】高并发编程终极指南:线程池优化、单例模式陷阱与死锁避坑实战
深入理解线程池设计与应用:高效并发编程的秘密 一. 线程池1.1 什么是线程池1.2 线程池的优点1.3 线程池的应用场景 二. 线程池设计三. 单例模式3.1 什么是单例模式3.2 单例模式特点3.3 实现单例模式方法3.3.1 饿汉实现⽅式3.3.2 懒汉实现⽅式 四. 线程安全和重入问题…...
学习和测试WebApi项目限制客户端ip访问接口(基于中间件)
WebApi项目需要限制仅允许有限的客户端访问接口,百度相关内容,网上很多介绍WebApi接口IP限流的文章,稍微调整就能用于限制IP访问,微软官网中也有文章介绍客户端 IP 安全列表(参考文献1),可以通过…...
闲鱼智能客服机器人-实现闲鱼平台7×24小时自动化值守
专为闲鱼平台打造的AI值守解决方案,实现闲鱼平台724小时自动化值守,支持多专家协同决策、智能议价和上下文感知对话。 🌟 核心特性 智能对话引擎 功能模块技术实现关键特性上下文感知会话历史存储轻量级对话记忆管理,完整对话历…...
Apache Ranger 2.2.0 编译
安装包下载: https://ranger.apache.org/download.html 编译环境: Linux centos7jdk 1.8maven 3.9.6gitpython 3 git 安装 yum -y install gitpython3安装 yum install epel-release -y yum install python3 python3-devel -y批量安装开发工具套件 …...
实战演练:用 AWS Lambda 和 API Gateway 构建你的第一个 Serverless API
实战演练:用 AWS Lambda 和 API Gateway 构建你的第一个 Serverless API 理论千遍,不如动手一遍!在前面几篇文章中,我们了解了 Serverless 的概念、FaaS 的核心原理以及 BaaS 的重要作用。现在,是时候把这些知识运用起来,亲手构建一个简单但完整的 Serverless 应用了。 …...
鱼眼相机生成-BEV鸟瞰图-入门教程
目录 原理介绍 1. IPM与BEV转换的核心原理 2. 尺度信息的来源 3. 尺度信息的准确性限制 4. 实际应用中的处理方法 代码实现: 360 BEV环视拼接算法 一、核心算法流程 三、实际应用挑战与优化 四、开源实现参考 原理介绍 1. IPM与BEV转换的核心…...
设计模式简述(十八)享元模式
享元模式 描述基本组件使用 描述 当内存中存在大量类似的对象时,可以考虑使用享元模式减少整体内存占用。 可以将相同的部分和不同的部分进行拆分,以达到多个对象共享相同部分内存的目的。 基本组件 通常享元对象通过共享的属性映射一个享元对象。 公…...
Google语法整理
以下是从整理出的 Google 语法: site:指定域名,如 “apache site:bbs.xuegod.cn”,可查询网站的收录情况 。 inurl:限定在 url 中搜索,如 “inurl:qq.txt”,可搜索 url 中包含特定内容的页面&a…...
【每日一题 | 2025年5.5 ~ 5.11】搜索相关题
个人主页:Guiat 归属专栏:每日一题 文章目录 1. 【5.5】P3717 [AHOI2017初中组] cover2. 【5.6】P1897 电梯里的尴尬3. 【5.7】P2689 东南西北4. 【5.8】P1145 约瑟夫5. 【5.9】P1088 [NOIP 2004 普及组] 火星人6. 【5.10】P1164 小A点菜7. 【5.11】P101…...
【MySQL】页结构详解:页的大小、分类、头尾信息、数据行、查询、记录及数据页的完整结构
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
C++ stl中的priority_queue的相关函数用法
文章目录 priority_queuepriority_queue定义方式priority_queue相关函数 priority_queue priority_queue 称为 优先级队列,默认使用vector作为底层存储数据的容器,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用…...
软件架构师知识点总结
一、综合知识 软件架构师综合知识总结-CSDN博客 二、案例 软件架构师案例知识点总结-CSDN博客 三、论文 1、题目类型:八大架构;系统开发(开发方法/模型、需求分析、测试等);系统可靠性、安全性、容错技术等&#…...
MySQL数据库常见面试题之三大范式
写在前面 此文章大部分不会引用最原始的概念,采用说人话的方式。 面试题:三大范式是什么?目的是什么?必须遵循吗? 假设有一张表(学号,姓名,课程,老师) 是…...
Scrapy 核心组件解析:Request Response 的深度应用与实战
Scrapy 是 Python 生态中最强大的爬虫框架之一,其核心组件 Request 和 Response 承担着数据抓取与处理的关键任务。本文深入解析 Scrapy 2.13.0 中 Request 和 Response 的高级用法,涵盖参数配置、回调函数、错误处理、子类扩展等,并结合 综合…...
mybatis执行sql过程
一、配置加载阶段 1. 读取全局配置(mybatis-config.xml) 入口类:SqlSessionFactoryBuilder.build()关键组件: XMLConfigBuilder:解析全局配置文件。Configuration:存储所有配…...
OceanBase 4.3版本向量数据库部署
OceanBase 4.3版本向量数据库部署 安装包准备最低资源配置重要的准备事项服务器配置操作系统内核参数BIOS设置磁盘挂载网卡设置 部署OAT工具初始化OBServer服务器使用oatcli部署OB集群安装OceanBase软件初始化OceanBase集群 启用向量检索功能 OceanBase最新的V4.3版本开始支持向…...
LeetCode 941. 有效的山脉数组 java题解
https://leetcode.cn/problems/valid-mountain-array/description/ 双指针 class Solution {public boolean validMountainArray(int[] arr) {int lenarr.length;if(len<3) return false;int left0,rightlen-1;while(left1<len&&arr[left]<arr[left1]){left…...
基于Java和高德开放平台的WebAPI集成实践-以搜索POI2.0为例
目录 前言 一、高德搜索API简介 1、高德开放平台 2、搜索功能介绍 3、部分API介绍 二、Uniapi集成高德API 1、API集成流程 2、访问接口的定义 3、业务调用集成 三、常见问题与优化 四、总结 前言 在当今数字化时代,地理信息系统(GISÿ…...
Docker拉取ubuntu22.04镜像使用ROS2 humble及仿真工具可视化进行导航
创建Ubuntu22.04 容器 docker pull ubuntu:22.04 #下载22.04镜像 docker images #查看已下载镜像 #根据镜像创建容器 sudo docker run -it -v /home/lab118/BD_ICL/tools_BD/cailib_data:/calib_data -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY:0 --nethost -e GDK_SCAL…...
PXE安装Ubuntu系统
文章目录 1. 服务器挂载Ubuntu镜像2. 修改dhcp配置文件3. 修改tftp配置文件4.复制网络驱动文件和其他配置文件5. http目录下配置文件6. 踩坑记录6.1 Failed to load ldlinux.c326.2 no space left on device6.3 为啥用pxe安装系统时,客户端需要较大的内存࿱…...
外网访问内网海康威视监控视频的方案:WebRTC + Coturn 搭建
外网访问内网海康威视监控视频的方案:WebRTC Coturn 需求背景 在仓库中有海康威视的监控摄像头,内网中是可以直接访问到监控摄像的画面,由于项目的需求,需要在外网中也能看到监控画面。 实现这个功能的意义在于远程操控设备的…...
缓存局部性保留
在操作系统中,线程切换相比进程切换更轻量级的关键原因之一是 缓存(Cache)的有效性,尤其是对 CPU 缓存(如 L1/L2/L3)和 TLB(Translation Lookaside Buffer)的影响。以下从缓存角度详…...
MyBatis源码解读5(3.1、缓存简介)
3.1、简介 我们需要记住一句话,程序与数据库之间的交互是性能瓶颈的关键,所以我们在做优化的时候,数据库的优化要做,但是优先级是最低的,比它优先级高的是方面是程序与数据库之间的交互,先从宏观上解决…...
【MySQL】行结构详解:InnoDb支持格式、如何存储、头信息区域、Null列表、变长字段以及与其他格式的对比
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
Docker 部署Nexus仓库 搭建Maven私服仓库 公司内部仓库
介绍 Nexus 是广泛使用的仓库管理工具,常用于管理 Java 构件(如 JAR、WAR、EAR 文件)。它可以作为一个本地的 Maven 仓库,用来存储和管理项目的依赖包和构建产物。支持多种仓库类型,能够帮助开发团队更高效地管理构件…...
PostgreSQL 的 pg_column_size 函数
PostgreSQL 的 pg_column_size 函数 pg_column_size 是 PostgreSQL 提供的一个系统函数,用于返回特定列或值在数据库内部存储时所占用的字节数。这个函数对于数据库优化、存储空间分析和性能调优非常有用。 函数语法 pg_column_size(anyelement)参数说明 anyele…...
【前端】【HTML】【总复习】一万六千字详解HTML 知识体系
🌐 HTML 知识体系 一、HTML 基础入门 1. HTML 简介与作用 HTML(HyperText Markup Language,超文本标记语言)是构建网页的基础语言。它的核心作用是: 定义网页内容的结构(标题、段落、图片、表格等)提供语义化标签,帮助搜索引擎与辅助设备理解页面内容配合 CSS 实现…...
支持向量机与逻辑回归的区别及 SVM 在图像分类中的应用
支持向量机与逻辑回归的区别及 SVM 在图像分类中的应用 在机器学习的多元算法领域中,支持向量机(SVM)和逻辑回归(LR)作为两种经典的监督学习算法,被广泛应用于各类分类任务。尽管它们有着相似的目标&#…...
MySQL基础面试题集锦
MySQL基础面试题集锦 一、SQL基础语法 1. 数据库和表操作 -- 创建数据库 CREATE DATABASE test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 创建表 CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,email VARCH…...
【网络分析工具】网络工具wireshark、TCPdump、iperf使用详解
这里写目录标题 1. wireshark1.1. 过滤包1.2. 常见分析 2. tcpdump3. iperf 1. wireshark **ip.dst eq 10.0.0.21** 是用于网络流量分析工具(例如 Wireshark 或 tcpdump)的过滤器表达式。 它的作用是筛选出所有目标IP地址为 10.0.0.21 的数据包 IP.add…...
【漫话机器学习系列】253.超平面(Hyperplane)
超平面(Hyperplane)详解:从二维到高维空间 在机器学习、深度学习、支持向量机(SVM)等领域中,经常会遇到一个重要的数学概念——超平面(Hyperplane)。但超平面究竟是什么?…...
#微调重排序模型:Reranking从入门到实践
🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创…...
vector 常见用法及模拟
文章目录 1. vector的介绍与使用1.1 vector的构造1.2 vector iterator 的使用1.3 有关大小和容量的操作1.4 vector 增删查改1.5 vector 迭代器失效问题(重点)1.6 vector 中二维数组的使用 2. vector 的模拟实现2.1 拷贝构造和赋值重载的现代写法2.2 memc…...
可变参数模板
引入:为什么会有可变参数模板? 在C98/03中,也就是我们之前学的类模版和函数模版中只能含固定数量的模版参数,而C11中新增的可变参数模板能够不固定数量的模版参数! 一:可变参数模板的格式 // Args是一个模板…...
缓存(5):常见 缓存数据淘汰算法/缓存清空策略
主要的三种缓存数据淘汰算法 FIFO(first in first out):先进先出策略,最先进入缓存的数据在缓存空间不够的情况下(超出最大元素限制)会被优先被清除掉,以腾出新的空间接受新的数据。策略算法主要比较缓存元素的创建时…...
深入了解linux系统—— 自定义shell
shell的原理 我们知道,我们程序启动时创建的进程,它的父进程都是bash也就是shell命令行解释器; 那bash都做了哪些工作呢? 根据已有的知识,我们可以简单理解为: 输出命令行提示符获取并解析我们输入的指令…...
【通讯录教程】如何将号码快速导入手机通讯录,支持苹果和安卓手机,一次性导入大量号码进入手机通讯录,基于WPF的解决方案
以下是一个基于WPF的解决方案,用于将大量号码快速导入苹果和安卓手机通讯录: 项目应用场景 企业员工通讯录批量导入:HR需要将数百名员工的联系方式快速导入公司手机客户关系管理:销售人员需要将大量客户信息导入…...
Git初始化相关配置
Git配置 在Git安装完成后,windows操作系统上会多出一个Git Bash的软件,如果是linux或者是macOS,那么直接打开终端,在终端中敲击命令即可 # 检查git版本 git -v # 或 git --version在使用git时,需要配置一下用户名和邮…...
n8n中订阅MQTT数据
第一步:创建mqtt登录证证 第二步:创建mqtt trigger组件,并配置凭证和订阅主题 第三步:创建Code节点,编写格式转换代码 第四步:创建转发MQTT节点,并配置MQTT凭证 第五步:启用工作流 整…...
Docker、ECS 与 K8s 网段冲突:解决跨服务通信中的路由问题
🧩 问题背景 在阿里云的项目中,在项目初期搭建过程中遇到了一个让人头疼的网络冲突问题:同一个 VPC 中的 Docker 容器和 Kubernetes 集群由于使用相同的网段,导致k8s pod连接ECS容器之间的网络连接失败。 背景环境: …...
《智能网联汽车 自动驾驶系统设计运行条件》 GB/T 45312-2025——解读
目录 1. 标准概述 2. 核心概念 3. 标准核心内容 3.1 一般要求 3.2 ODC基础元素层级 3.3 ODC元素具体要求 3.4 附录A(ODC示例) 4. 技术挑战与实施建议 5. 标准意义 原文链接:国家标准|GB/T 45312-2025 (发布:2…...
AARRR用户增长模型(海盗指标)详解
目录 一、模型起源与概述二、五大阶段详解1. 获取(Acquisition)1.1 定义1.2 关键指标 2. 激活(Activation)2.1 定义2.2 关键指标 3. 留存(Retention)3.1 定义3.2 关键指标3.3 提升留存手段案例3.4 互联网留…...
CSS专题之自定义属性
前言 石匠敲击石头的第 12 次 CSS 自定义属性是现代 CSS 的一个强大特性,可以说是前端开发需知、必会的知识点,本篇文章就来好好梳理一下,如果哪里写的有问题欢迎指出。 什么是 CSS 自定义属性 CSS 自定义属性英文全称是 CSS Custom Proper…...
JVM——Java字节码基础
引入 Java字节码(Java Bytecode)是Java技术体系的核心枢纽,所有Java源码经过编译器处理后,最终都会转化为.class文件中的字节码指令。这些指令不依赖于具体的硬件架构和操作系统,而是由Java虚拟机(JVM&…...
【React中useRef钩子详解】
一、useRef的核心特性 useRef是React提供的Hook,用于在函数组件中创建可变的持久化引用,具有以下核心特性: 持久化存储 返回的ref对象在组件整个生命周期内保持不变,即使组件重新渲染,current属性的值也不会丢失。无触发渲染 修改ref.current的值不会导致组件重新渲染,适…...
《AI大模型应知应会100篇》第58篇:Semantic Kernel:微软的大模型应用框架
第58篇:Semantic Kernel:微软的大模型应用框架 ——用C#和Python构建下一代AI应用的统一编程范式 📌 摘要 随着大模型(LLM)技术的快速发展,如何将这些强大的语言模型与传统代码系统进行无缝集成ÿ…...
ssh -T git@github.com 测试失败解决方案:修改hosts文件
问题描述 通过SSH方式测试,使用该方法测试连接可能会遇到连接超时、端口占用的情况,原因是因为DNS配置及其解析的问题 ssh -T gitgithub.com我们可以详细看看建立 ssh 连接的过程中发生了什么,可以使用 ssh -v命令,-v表示 verbo…...
c++面向对象:接口设计
一、什么是接口(Interface)? 在面向对象编程中,接口可以理解为一种“规范”或“约定”。 更具体一点: 它定义了“某个对象”应该具备哪些功能(方法、行为)但不关心这些功能的具体实现细节 用…...
[Java][Leetcode middle] 80. 删除有序数组中的重复项 II
删除重复元素,最多只保留两个 1. 计数法 第一个元素直接加入当与前一个元素相同时,计数器1,不同时计数器恢复1; 只有计数器小于2时,记录元素; public int removeDuplicates2(int[] nums) {int cnt 1;in…...
【Bluedroid】蓝牙HID DEVICE断开连接流程源码分析
蓝牙HID(Human Interface Device)的断开连接流程涉及从应用层到协议栈的多层交互。本文通过剖析Android Bluetooth协议栈代码,梳理从上层调用disconnect()到最终物理链路断开的完整流程,涵盖状态检查、消息传递、L2CAP通道关闭、资…...