多线程杂谈:惊群现象、CAS、安全的单例
引言
本文是一篇杂谈,帮助大家了解多线程可能会出现的面试题。
目录
引言
惊群现象
结合条件变量
CAS原子操作(cmp & swap)
线程控制:两个线程交替打印奇偶数
智能指针线程安全
单例模式线程安全
最简单的单例(懒汉)模式
惊群现象
惊群效应(Thundering Herd Effect)是一个在计算机科学和网络领域中常见的现象,特别是在并发编程和分布式系统中。这个效应描述的是当多个进程或者线程几乎同时被唤醒或激活去处理一个任务或事件,但实际上只需要其中的一部分进程或线程来处理,导致资源的浪费和性能的下降。
下面详细解释一下惊群效应的几个关键点:
### 发生场景
1. **网络服务中的请求处理**:在处理网络请求时,如果有大量的请求同时到达,系统可能会唤醒所有的处理线程,但实际上只需要少数线程就能处理这些请求。
2. **锁竞争**:在多线程编程中,当多个线程试图获取同一个锁时,一旦锁被释放,所有的等待线程都可能被唤醒,但只有一个线程能够获得锁,其他线程将继续等待。
3. **事件驱动系统**:在事件驱动的系统中,一个事件可能会使得多个处理者被唤醒,但实际上只需一个处理者处理该事件。
### 原因
1. **同步机制**:系统中的同步机制(如信号量、锁等)可能会唤醒所有等待的进程或线程。
2. **缺乏精细的调度**:调度器没有足够的信息来决定应该唤醒哪些进程或线程,因此默认唤醒所有等待者。
### 影响
1. **性能下降**:不必要的进程或线程唤醒会导致上下文切换,增加CPU的负载,降低系统的响应速度和吞吐量。
2. **资源浪费**:唤醒过多的进程或线程会占用内存和其他系统资源,而这些资源实际上并不需要立即使用。
### 解决方案
1. **使用更精细的锁**:比如读写锁,可以允许多个读操作同时进行,而写操作则互斥。
2. **改进调度算法**:调度器可以根据特定的策略只唤醒必要的进程或线程。
3. **领导者选举**:在处理事件时,可以先选举一个领导者来处理事件,其他线程保持睡眠状态。
4. **使用消息队列**:通过消息队列来分配任务,只有当任务到达时才唤醒处理线程。
惊群效应是系统设计时需要考虑的一个重要问题,通过合理的设计和优化,可以有效地避免或减轻这一效应带来的负面影响。
根据之前提到的惊群效应及其影响,以下是一些具体的解决方案:
使用单线程或有限线程模型:
工作者线程(Worker Threads)模式:预先创建一定数量的工作者线程,每个线程从任务队列中获取并处理任务,避免同时唤醒过多线程。
线程池:通过线程池管理线程,可以限制同时运行的线程数量,避免创建过多的线程。
改进锁机制:
条件变量:使用条件变量来唤醒特定的线程,而不是所有等待的线程。
读写锁(Reader-Writer Lock):允许多个读操作同时进行,而写操作则互斥,减少锁竞争。
领导选举机制:
在处理特定任务时,通过选举机制选择一个线程作为领导者来处理任务,其他线程进入等待状态。
事件通知机制:
使用事件通知而不是轮询,只有当特定事件发生时才唤醒相关的线程。
消息队列:
通过消息队列来分配任务,线程可以根据队列中的消息来决定是否需要处理任务,减少不必要的唤醒。
负载均衡:
在分布式系统中,通过负载均衡技术将任务均匀分配到不同的服务器或线程上,避免某些节点过载。
细粒度锁:
使用细粒度锁代替粗粒度锁,减少锁的竞争范围,从而减少同时唤醒的线程数量。
限流和背压机制:
在系统层面实施限流策略,当系统负载过高时,通过背压机制告知上游减少请求发送,避免系统过载。
异步处理:
采用异步编程模型,任务提交后立即返回,实际处理在后台异步进行,减少线程等待和上下文切换。
通过上述解决方案,可以有效地减少惊群效应的发生,提高系统的性能和资源利用率。
结合条件变量
2. **锁竞争**:在多线程编程中,当多个线程试图获取同一个锁时,一旦锁被释放,所有的等待线程都可能被唤醒,但只有一个线程能够获得锁,其他线程将继续等待。
为什么把这一条添加进去呢?
这就要牵扯到wait与唤醒机制了。
唤醒时,一旦错误唤醒,就会出现恶性竞争。
CAS原子操作(cmp & swap)
整个处理流程中,假设内存中存在一个变量i,它在内存中对应的值是A(第一次读取),此时经过业务处理之后,要把它更新成B,那么在更新之前会再读取一下i现在的值C,如果在业务处理的过程中i的值并没有发生变化,也就是A和C相同,才会把i更新(交换)为新值B。如果A和C不相同,那说明在业务计算时,i的值发生了变化,则不更新(交换)成B。最后,CPU会将旧的数值返回。而上述的一系列操作由CPU指令来保证是原子的(来自程序新视界)。
在《Java并发编程实践》中对CAS进行了更加通俗的描述:我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少。
线程控制:两个线程交替打印奇偶数
// t1打印奇数
// t2打印偶数
// 交替打印
int main()
{mutex mtx;int x = 1;condition_variable cv;bool flag = false;// 如果保证t1先运行 condition_variable+flag// 交替运行thread t1([&]() {for (size_t i = 0; i < 10; i++){unique_lock<mutex> lock(mtx);if (flag)cv.wait(lock);cout << this_thread::get_id() << ":" << x << endl;++x;flag = true;cv.notify_one(); // t1notify_one的时候 t2还没有wait}});thread t2([&]() {for (size_t i = 0; i < 10; i++){unique_lock<mutex> lock(mtx);if (!flag)cv.wait(lock);cout << this_thread::get_id() << ":" << x << endl;++x;flag = false;cv.notify_one();}});t1.join();t2.join();return 0;
}
这是一道面试题,要求两个线程按顺序打印。
怎么保证线程一先运行呢?条件变量 + flag。(第一次不让线程一wait,而是线程2wait)
第一次的notify_one不起作用。
智能指针线程安全
template<class T>class shared_ptr{public:// RAIIshared_ptr(T* ptr = nullptr):_ptr(ptr),_pcount(new atomic<int>(1)){}template<class D>shared_ptr(T* ptr, D del):_ptr(ptr), _pcount(new atomic<int>(1)), _del(del){}// function<void(T*)> _del;void release(){if (--(*_pcount) == 0){//cout << "delete->" << _ptr << endl;//delete _ptr;_del(_ptr);delete _pcount;}}~shared_ptr(){release();}shared_ptr(const shared_ptr<T>& sp):_ptr(sp._ptr), _pcount(sp._pcount){++(*_pcount);}// sp1 = sp3shared_ptr<T>& operator=(const shared_ptr<T>& sp){if (_ptr != sp._ptr){release();_ptr = sp._ptr;_pcount = sp._pcount;++(*_pcount);}return *this;}// 像指针一样T& operator*(){return *_ptr;}T* operator->(){return _ptr;}int use_count() const{return *_pcount;}T* get() const{return _ptr;}private:T* _ptr;//int* _pcount;atomic<int>* _pcount;function<void(T*)> _del = [](T* ptr) {delete ptr; };};
智能指针在拷贝构造的时候,内部的计数器++。万一两个线程都对智能指针调用拷贝构造,那么计数器就会错乱。
我们可以:1.上锁 2.atomic保护智能指针。
在目前的C++中,更新了如下的关于智能指针的安全性:
-
引用计数的线程安全性:
std::shared_ptr
对其内部的引用计数的操作(增加或减少)是线程安全的。这意味着多个线程可以安全地共享和复制同一个std::shared_ptr
实例,而无需额外的同步机制。例如,在不同线程中拷贝同一个std::shared_ptr
实例不会导致数据竞争。 -
对象内容的线程安全性:
std::shared_ptr
不会对其管理的对象的内容进行任何保护,如果多个线程同时读写由std::shared_ptr
管理的对象,那么就需要手动确保对该对象的访问是线程安全的。--只是提供RAII封装 -
实例本身的线程安全性:对同一个
std::shared_ptr
实例的读写操作(例如,赋值和重置)是不安全的,需要额外的同步。
注意:shared_ptr(这个指针类)本身是线程安全的,但是他RAII指向的资源操作的时候不能保证线程安全。
我们可以理解为访问shared_ptr这个“壳子”的时候,是线程安全的,但是对“壳子”包含的对象不安全。
单例模式线程安全
懒汉模式的线程安全:由于即用即取,万一两个线程并发进行懒汉申请,那么就会出现线程安全,加锁就可以。
//2、提供获取单例对象的接口函数
static Singleton& GetInstance(){
if(_pslnst==nullptr)
{
//t1 t2
unique_lock<mutex>lock(_mtX);
if(_psinst==nullptr)
{
//第一次调用Getlnstance的时候创建单例对象
_psinst=newSingleton;
}
}
return*_psinst;
}
当后续存在单例之后,就需要重复的申请锁,减少了资源消耗。
同时双重判断也提供了保险机制。
最简单的单例(懒汉)模式
//懒汉
class Singleton {
public:// 2、提供获取单例对象的接口函数static Singleton* GetInstance() {// 局部的静态对象,是在第一次调用时初始化static Singleton inst;return &inst;}
private:// 1、构造函数私有Singleton() {cout << "Singleton()" << endl;}
};
私有构造--静态方法获取static实例。
注意:这是线程安全的!--静态局部对象只初始化一次!
局部的静态对象,是在第一次调用时初始化
C++11之前,他不是,也就说,C++11之前的编译器,那么这个代码不安全的
C++11之后可以保证局部静态对象的初始化是线程安全的,只初始化一次(不会获得两个实例)
相关文章:
多线程杂谈:惊群现象、CAS、安全的单例
引言 本文是一篇杂谈,帮助大家了解多线程可能会出现的面试题。 目录 引言 惊群现象 结合条件变量 CAS原子操作(cmp & swap) 线程控制:两个线程交替打印奇偶数 智能指针线程安全 单例模式线程安全 最简单的单例&…...
Nginx调优
Nginx 是一个高性能的反向代理服务器和负载均衡器,在处理大量并发请求时表现出色。但是,随着系统负载的增加,Nginx 的性能可能受到多方面的影响,因此进行适当的调优至关重要。以下是 Nginx 调优的几个方向和关键点: 1…...
自定义UITableViewCell
很多时候,我们是不能直接使用系统自带的UITableViewCell,因为自带的比较简单只有一个UIImageView和两个UILabel,假设需要多个UIImageView或者两个以上UILabel,那就需要自定义了。本文就实现如何自定义UITableViewCell。 假设我们现…...
Java 基于微信小程序的原创音乐小程序设计与实现(附源码,部署,文档)
大家好,我是stormjun,今天为大家带来的是Java实战项目-基于微信小程序的原创音乐小程序设计与实现。该系统采用 Java 语言 开发,MySql 作为数据库,系统功能完善 ,实用性强 ,可供大学生实战项目参考使用。 博…...
MySQL —— 事务
概念 事务把组SQL语句打包成为个整体,在这组SQL的执行过程中,要么全部成功,要么全部失败。 这组SQL语句可以是条也可以是多条。 ACID 特性 原子性 Atomicity(原子性):一个事务中的所有操作,要么全部成功࿰…...
【大模型】ChatGPT 高效处理图片技巧使用详解
目录 一、前言 二、ChatGPT 4 图片处理介绍 2.1 ChatGPT 4 图片处理概述 2.1.1 图像识别与分类 2.1.2 图像搜索 2.1.3 图像生成 2.1.4 多模态理解 2.1.5 细粒度图像识别 2.1.6 生成式图像任务处理 2.1.7 图像与文本互动 2.2 ChatGPT 4 图片处理应用场景 三、文生图操…...
SpringBoot注入配置文件application.properties中的信息
问题:将可能会变动的配置信息硬编码在代码中,在修改时难以定位,且过于繁琐,怎么办? 解决:自定义application.properties配置文件中的信息,注意严格遵循ab的形式,不要加引号…...
大数据,Hadoop,HDFS的简单介绍
大数据 海量数据,具有高增长率、数据类型多样化、一定时间内无法使用常规软件工具进行捕捉、管理和处理的数据集 合 大数据的特征: 4V Volume : 巨大的数据量 Variety : 数据类型多样化 结构化的数据 : 即具有固定格式和有限长度的数据 半结构化的数据 : 是…...
第15章:Python TDD应对货币类开发变化(二)
写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...
黑马点评之导入初始项目(java)
!!!由于我一开始是在网盘上下载的资源,后面忙活半天,发现代码是不完整的,才知道需要在github上面拉取初始代码。 然后第二点是我的本地环境是jdk21,但是他原本的代码为jdk8,所以在换…...
Erlang语言的语法糖
Erlang语言的语法糖:简化编程的灵活工具 Erlang是一种功能强大的编程语言,最初由爱立信(Ericsson)为电信系统开发。它以其高并发性、容错性和分布式特性而闻名,特别适合构建实时系统。然而,Erlang的语法相…...
数据库基础知识:记录、表、字段、数据类型、约束、主键、外键、规范化、索引、序列
数据库是由一个或多个有组织的数据集合组成,而数据库管理系统(DBMS)是操作数据库的软件,包括很多人本科上课学过的SQL Server,现在常用的MySQL、Postgresql等,用于提供数据的存储、访问、运行和维护等。学习…...
Centos 8 交换空间管理
新增swap 要增加 Linux 系统的交换空间,可以按照以下步骤操作: 1. 创建一个交换文件 首先,选择文件路径和大小(例如,增加 1 GB 交换空间)。 sudo fallocate -l 1G /swapfile如果 fallocate 不可用&…...
迈向 “全能管家” 之路:机器人距离终极蜕变还需几步?
【图片来源于网络,侵删】 这是2024年初Figure公司展示的人形机器人Figure 01,他可以通过观看人类的示范视频,在10小时内经过训练学会煮咖啡,并且这个过程是完全自主没有人为干涉的! 【图片来源于网络,侵删】…...
Data Filtering Network 论文阅读和理解
目录 一、TL;DR 二、Introduction 2.1 apple的结论 2.2 业界做法: 2.3 我们的做法(Apple) 2.4 如何获取好的DFN 三、未完待续(这周出去购物了,下周继续补充) 一、TL;DR 核心…...
KMP算法
KMP算法详解 KMP(Knuth-Morris-Pratt)算法是一种用于在大串中寻找小串的字符串匹配算法。它通过在字符串匹配过程中避免不必要的重复比较,显著提高了效率。KMP算法的核心思想是利用字符串中已经匹配的部分信息来优化匹配过程,减少…...
分类操作,可以通过引入对 Bean 的前置和后置处理
深入理解 BeanPostProcessor BeanPostProcessor,它主要有两个方法before和after的执行阶段,主要就是明白方法是在谁的前面在谁的后面执行 在你的idea中创建一个项目,你可以通过实现Ordered这个接口来,这样就可以让其实现类去实现…...
【2024 年度总结】从小白慢慢成长
【2024 年度总结】从小白慢慢成长 1. 加入 CSDN 的契机2. 学习过程2.1 万事开头难2.2 下定决心开始学习2.3 融入技术圈2.4 完成万粉的目标 3. 经验分享3.1 工具的选择3.2 如何提升文章质量3.3 学会善用 AI 工具 4. 保持初心,继续前行 1. 加入 CSDN 的契机 首次接触…...
无数据库开源Wiki引擎WikiDocs
简介 什么是 WikiDocs ? WikiDocs 是一个无数据库的开源 Markdown 文件平面 Wiki 引擎。它旨在提供一个简单、灵活且易于使用的 Wiki 解决方案,允许用户创建和管理文档而无需依赖传统数据库。 主要特点 无数据库:使用纯文本文件存储数据&am…...
【算法】字符串:高精度计算之加法、乘法(数组模拟)
目录 1、高精度算法是什么? 2、易错点 高精度加法: 高精度减法: 高精度乘法: 高精度除法: 3、高精度加法 思路: 例题 4、高精度乘法 思路 例题 参考文章 高精度算法——数组模拟(加、减…...
4.JoranConfigurator解析logbak.xml
文章目录 一、前言二、源码解析GenericXMLConfiguratorlogback.xml解析通过SaxEvent构建节点model解析model节点DefaultProcessor解析model 三、总结 一、前言 上一篇介绍了logback模块解析logback.mxl文件的入口, 我们可以手动指定logback.xml文件的位置, 也可以使用其它的名…...
JavaWeb开发(十六)实战-生鲜后台管理系统(三)BeanUtils介绍、Servlet的抽取
1. 生鲜后台管理系统-BeanUtils的使用 1.1. BeanUtils介绍 BeanUtils 是 Apache commons组件的成员之一,主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据,也可以将一个表单提交的所有数据封装到JavaBean中。使用第三方工具&am…...
人形机器人将制造iPhone!
前言 优必选机器人和富士康通过一项突破性的合作伙伴关系,正在将先进的人形机器人(如Walker S1及其升级版Walker S2)整合到制造流程中,以改变iPhone的生产方式。这一合作旨在通过提升机器人能力、优化工作流程以及实现更智能的自动…...
Oracle 深入学习 Part 14:Managing Password Security and Resources(管理密码安全性和资源)
Profiles Profile 是一个以名称标识的集合,用于管理 密码 和 资源限制。 每个用户都对应一个profiles,可以通过 CREATE USER 或 ALTER USER 命令分配给用户。 Profiles 可以启用或禁用。 Profiles 可以关联到默认的 DEFAULT Profile。 密码管理&…...
202209 青少年软件编程等级考试C/C++ 二级真题答案及解析(电子学会)
第 1 题 统计误差范围内的数 统计一个整数序列中与指定数字m误差范围小于等于X的数的个数。 时间限制:5000 内存限制:65536 输入 输入包含三行: 第一行为N,表示整数序列的长度(N <= 100); 第二行为N个整数,整数之间以一个空格分开; 第三行包含2个整数,为指定…...
qt中透明度表示
透明度的表示方法 在 Qt 样式表中,使用 rgba 或 argb 颜色表示法时,透明度通常用一个介于 0 和 1 之间的小数表示。 rgba 表示法:rgba(red, green, blue, alpha),其中 alpha 是透明度,例如 rgba(255, 0, 0, 0.5) 表示…...
Mybatis 进阶 / Mybatis—Puls (详细)
目录 一.动态SQL 1.1标签 1.2 标签 1.3标签 1.4标签 1.5标签 1.6标签 mybatis总结: 二.Mybatis-Puls 2.1准备工作 2.2CRUD单元测试 2.2.1创建UserInfo实体类 2.2.2编写Mapper接⼝类 2.2.3 测试类 2.3 常见注解 2.3.1TableName 2.3.2TableField 2.4打印日…...
opencv在图片上添加中文汉字(c++以及python)
opencv在图片上添加中文汉字(c以及python)_c opencv绘制中文 知乎-CSDN博客 环境: ubuntu18.04 desktopopencv 3.4.15 opencv是不支持中文的。 这里C代码是采用替换原图的像素点来实现的,实现之前我们先了解一下汉字点阵字库。…...
js截取video视频某一帧为图片
1.代码如下 <template><div class"box"><div class"video-box"><video controls ref"videoRef" preload"true"src"https://qt-minio.ictshop.com.cn:9000/resource-management/2025/01/08/7b96ac9d957c45a…...
Observability:最大化可观察性 AI 助手体验的 5 大提示(prompts)
作者:来自 Elastic Zoia_AUBRY 在过去三年担任客户工程师期间,我遇到了数百名客户,他们最常问的问题之一是:“我的数据在 Elastic 中;我该如何利用它获得最大优势?”。 如果这适用于你,那么本…...
HDFS的架构优势与基本操作
目录 写在前面一、 HDFS概述 1.1 HDFS简介1.2 HDFS优缺点 1.2.1 优点1.2.2 缺点 1.3 HDFS组成架构1.4 HDFS文件块大小 二、HDFS的Shell操作(开发重点) 2.1 基本语法2.2 命令大全2.3 常用命令实操 2.3.1 上传2.3.2 下载2.3.3 HDFS直接操作 三、HDFS的AP…...
hive表修改字段类型没有级连导致历史分区报错
一:问题背景 修改hive的分区表时有级连概念,指字段的最新状态,默认只对往后的分区数据生效,而之前的分区保留历史元数据状态。好处就是修改语句的效率很快,坏处就是如果历史分区的数据还有用,那就回发生分…...
023:到底什么是感受野?
本文为合集收录,欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请查看这里。 在前面介绍卷积算法时,一直在强调一个内容,那就是卷积算法的运算过程是—— 卷积核在输入图像上滑动扫描的过程。 在每一次扫描时,可以…...
GoFrame g.* 方法和数据类型
GoFrame g.* 方法和数据类型 GoFrame 框架通过 g.* 方法提供了一系列常用的数据类型和对象获取方法。这个模块采用强耦合设计,目的是为开发者提供便捷的类型和对象调用方式。 使用方式 import "github.com/gogf/gf/v2/frame/g"数据类型 基础类型别名 …...
分苹果,若a ^ b ^ c = 0意味着:a 和 (b ^ c) 的值相等,或者 b 和 (a ^ c) 的值相等,以及 c 和 (a ^ b) 的值相等。
若a ^ b ^ c faultSum,那么faultSum 0时,即可产生上面的平分方案。说明可以满足二进制平分 #include<bits/stdc.h> using namespace std; int main() { int n; cin>>n; vector<int> weight(n); for(int i0;i<n;i) {…...
深入解析人工智能中的协同过滤算法及其在推荐系统中的应用与优化
目录 什么是协同过滤算法核心原理基本步骤相似度计算代码实现详解1.流程图2.创建基础的数据结构存储用户评分数据3.计算用户相似度4.获取相似用户5.推荐方法 算法优化建议1. 数据预处理优化去除异常值和噪声数据进行数据标准化使用稀疏矩阵优化存储 2. 相似度计算优化使用局部敏…...
电梯系统的UML文档04
这个版本的类图是直接从4.2节中用例图的描述得来的,这个视图中的类覆盖了系统所有的功能。我们用电梯类和电梯控制器类(ElevatorControl)移动或停止电梯;用门类开门或关门;用指示器类让乘客知道电梯的位置和方向&#…...
《自动驾驶与机器人中的SLAM技术》ch4:预积分学
目录 1 预积分的定义 2 预积分的测量模型 ( 预积分的测量值可由 IMU 的测量值积分得到 ) 2.1 旋转部分 2.2 速度部分 2.3 平移部分 2.4 将预积分测量和误差式代回最初的定义式 3 预积分的噪声模型和协方差矩阵 3.1 旋转部分 3.2 速度部分 3.3 平移部分 3.4 噪声项合并 4 零偏的…...
海量数据的处理
一般来说都是针对数据量特别大,内存有限制的。 第一类:topk问题 比如,在海量数据中找前50大的数据怎么办? 方法一:使用小顶堆,用小顶堆维护这50个元素,当有新元素到来时,直接与堆…...
Python人脸识别库DeepFace使用教程及源码解析
目录 一、DeepFace介绍 1、人脸库设计 2、DeepFace.find 3、DeepFace.verify 4、DeepFace.analyze 5、DeepFace.extract_faces 6、DeepFace.represent 7、DeepFace.stream 二、DeepFace二次开发 1、开发活体检测API 2、模型权重持久化 三、总结 一、DeepFace介绍 …...
Nacos:使用PgSQL数据源
数据源插件开源仓库地址:nacos-datasource-extend-plugins 一、PostgreSQL数据库安装 1、本文使用Docker进行数据库的安装,使用docker命令拉取的PG14版本的数据库: docker pull postgres:14.6 2、创建PG容器并启动,映射了5432…...
基于Python的多元医疗知识图谱构建与应用研究(下)
五、基于医疗知识图谱的医疗知识图谱程序构建 5.1 数据层构建 5.1.1 数据源选择与获取 在构建基于医疗知识图谱的医疗知识图谱数据层时,数据源的选择与获取至关重要。数据源的质量和丰富度直接决定了知识图谱的可靠性和实用性。医学文献是重要的数据源之一,包括学术期刊论…...
JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南
1、简述 在复杂的业务系统中,订单流程往往需要一系列的操作,比如验证订单、检查库存、处理支付、更新订单状态等。责任链模式(Chain of Responsibility)可以帮助我们将这些处理步骤分开,并且以链式方式处理每一个操作…...
SpringBoot多级配置文件
1.问题先导 有这样的场景,我们开发完毕后需要测试人员进行测试,由于测试环境和开发环境的很多配置都不相同,所以测试人员在运 行我们的工程时需要临时修改很多配置,如下 java –jar springboot.jar –-spring.profiles.activete…...
阿里云安装mikrotik7配置内网互通
阿里云近期推出了200M不限量机器,对于没有公网接入的中小企业可以借助这个机器对多地分支机构进行内网互通。目前已经有很多机构用这个搞跨云k8s,跨云集群了。 mikrotik作为一个商用的软件,操作性比一些开源的软件好用不少。 本文使用的网段为172.16.1…...
std::forward实现原理与应用场景
std::forward 是 C11 引入的一个函数模板,用于实现完美转发(Perfect Forwarding)。它的核心作用是根据传入的参数,决定将参数以左值引用还是右值引用的方式进行转发,从而保持参数的原始值类别。 实现原理 template&l…...
TiDB 在市面上的热门应用领域
TiDB 在市面上的热门应用领域 TiDB 作为一款分布式数据库,凭借其高可扩展性和强一致性,逐渐成为多个行业和领域的热门选择。那么,TiDB 在市面上主要应用在哪些领域呢?今天我们来看看 TiDB 在几个热门领域的应用场景。 1. 互联网…...
“深入浅出”系列之C++:(11)推荐一些C++的开源项目
1. SQLiteCpp - 简单易用的Sqlite C封装库 仓库地址:https://github.com/SRombauts/SQLiteCpp 简介:SQLiteCpp是一个对Sqlite数据库进行C封装的开源库,代码行数约2,500行。它提供了简洁易用的接口,使得在C项目中操作Sqlite数据库…...
高等数学学习笔记 ☞ 定积分的积分方法
1. 定积分的换元积分法 1. 换元积分公式:设函数在闭区间上连续,令,若满足: ①:当时,;当时,。 此时的大小关系不一定,但与最好对应着写,否则就要留意变号的问…...
KVA教程-插件开发
“如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 KVA 技术教程 * 插件开发 简介 插件开发是KVA&a…...