KalosAner Blog

「山穷水复疑无路,柳暗花明又一村。」

C++ 标准库条件变量用法

一、引言 在多线程编程中,经常会有进程之间相互依赖的情况,最典型的情况就是生产者消费者模型。 二、条件变量 如果线程 A 的部分代码的执行需要依赖于线程 B 中的代码,线程 A 就需要等待线程 B 执行了被依赖的代码之后才可以执行,所以线程 A 需要一种方法可以在线程 B 中的代码执行完成后得到通知。这时就可以使用条件变量。 以生产者消费者模型为例 1 2 3 4 using na...

C++ 标准库信号量用法

一、引言 信号量就像一个原子类型的整型全局变量,可以进行增减,但是同时只能有一个线程进行操作。它也适用于生产者消费者模型。 二、信号量

C++ struct 对齐规则

一、引言 C++ struct 的大小通常不会直接等于各个成员大小的总和,这是因为太过精细地分配内存会导致内存分配和访问的效率过低,所以一般对于不同大小的成员会采取对齐规则来分配内存。 结构体的地址和结构体中第一个成员的地址相同。 二、对齐规则 结构体在对齐时,对于没有用到的空间使用空白字节填充。 规则一:结构体的成员按照定义顺序依次置于内存,每个成员按照自身大小对齐。 ...

如何确定合适的线程数

一、引言 在多线程编程中,线程的数量会影响并发的性能。 过多的线程会消耗更多的资源,包括: 内存:pthread_create 创建出来的线程每个线程需要传递一个函数,所以每个线程都需要分配一个栈空间,占 8192 bytes(ulimit -a:查询栈空间大小)。std::thread 每个线程占用的空间可能较小。 切换:线程切换上下文会消耗 CPU 和时间。 并且大量唤醒的线程...

阻塞、非阻塞、同步、异步

一、引言 简单梳理一下 IO 操作中阻塞、非阻塞、同步、异步等概念。 典型的一次 IO 都有两个阶段:数据就绪、数据读写。 大部分 IO 函数都会有内核缓冲区和用户缓冲区。当内核缓存区中有数据可以读或者有空间可以写就是数据就绪阶段,然后就可以进行数据读写。 二、阻塞与非阻塞 阻塞和非阻塞区别在于调用函数的线程是否需要等待结果。 阻塞:当一个线程调用阻塞 IO 函数时,该线程就...

C++ 标准库 thread 类的用法

一、引言 std::thread 是 C++11 引入的线程管理类,用于创建和管理多线程程序,可以跨平台使用。使用该类需要在头文件引入 #include <thread> 并且在 Linux 下编译时需要链接 pthread 库。 常用的函数的函数原型: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...

C++ 学习资料整理

以下资料于 2025.03.31 开始整理。 看过的文章 分布式系统 分布式存储系统的一致性是什么?:分布式存储的一致性,主要是读写数据的一致性,某些情况下可以容忍读旧数据。noSQL 和 SQL 在分布式系统有很大区别。 共识算法(整理):主要用来解决分布式系统中各个阶段的决策统一问题,尤其是拜占庭问题,拜占庭错误算是分布式系统中一个最极端的问题,某个算法解决了这个问题,就可以说这...

C++ 内联函数

一、引言 内联(inline)函数的主要作用就是在编译阶段把内联函数的代码直接复制到调用该代码的地方。这样做可以省去调用函数的开销,提高效率。但是当调用该函数的地方太多时,会导致汇编代码过长,而且会增长编译时间。此外,内联函数不可以是递归函数,并且通常建议 inline 函数不超过 10 行代码。 inline 必须在函数定义时才生效,仅在函数声明时添加无效。 二、C++ 17...

五笔字型字根表


程序 CPU 占用率较高如何排查

一、定位 定位到对应的进程,然后因为线程是 CPU 调度的最小单位,找到进程中的线程。 二、分析 CPU 过高可能的原因: 1、代码逻辑问题:死循环或者时间复杂度过高 2、多线程并发:自旋锁滥用(忙等待持续占用 CPU) 3、频繁内存分配释放,缓存未命中 4、频繁的系统调用 三、解决 对于自旋锁可以优化成互斥锁 内存分配频繁可以使用内存池 缓存未命中通常需要设置线程的亲...