这一章是继上一章“保护共享数据”之后的进阶,核心是解决线程间的“等待”与“通知”问题,即一个线程如何高效地等待另一个线程完成某个操作。
等待一个事件
假如你正在坐一趟夜间火车,
你需要在正确的站点下车。现在有三种策略可以选择:
策略1:忙等待 (Busy-Waiting),
也就是整晚不睡,每到一站都探出头去看。优点是绝对不会错过下车点,
但缺点是极度疲劳(浪费CPU)。
策略...
为并发设计
首先,
什么是并发数据结构?一个并发数据结构是指一个可以被多个线程同时访问的数据结构。
也就是说, 其最低要求是线程安全 (Thread Safety)
这意味着,即使多个线程并发地对数据结构执行操作(无论是相同还是不同的操作),数据结构也必须保持其内部一致性:
无数据丢失或损坏。
所有的不变量 (Invariants)
必须始终保持(或者说,没有线程能看到不变...
内存模型基础
C++是一个系统级别的编程语言,标准委员会的目标之一就是不需要比C++还要底层的高级语言。C++应该向程序员提供足够的灵活性,无障碍的去做他们想要做的事情;当需要的时候,可以让他们“接触硬件”。原子类型和原子操作就允许他们“接触硬件”,并提供底层级别的同步操作,通常会将常规指令数缩减到1~2个CPU指令。
对象和内存位置
在一个C++程序中的所有数据都是由对象(objec...
concepts 概念
概念 (Concept)
是一种编译期谓词(predicate),它是一种直接在语言层面用来约束(constrain)模板参数的特性。
简单来说,它允许你清晰地声明:“这个模板参数 T
必须满足某些要求”(例如,T 必须是一个整数,或者 T 必须有一个 .begin()
成员函数)。
具体见(CPP++.md)
jthread
C++20 引入了 st...
进程的基本概念 (Process
Concept)
什么是进程 (Process)
一个进程是 “一个正在执行中的程序”
。它不仅仅是代码,还包含了程序当前的活动状态 。
一个进程在内存中通常包含以下几个部分 :
文本段 (Text Section):存放程序代码 。
数据段 (Data Section):存放全局变量 。
堆 (Heap):用于动态分配的内存 。
栈 ...
C++ 的类型转换分为两大类:隐式类型转换和显式类型转换
隐式类型转换 (Implicit
Type Conversion)
隐式类型转换是由编译器自动进行的,无需程序员显式指定。这通常发生在以下几种情况:
算术转换 (Arithmetic
Conversion):在混合类型的算术表达式中,较小的类型会被提升(promote)为较大的类型以保证精度。
1234// 例如:in...
std::array 是在 C++11
中引入的一个容器模板,它封装了一个固定大小的数组。它结合了C风格数组的性能优势(静态分配、无额外开销)和STL容器的便利性与安全性。
12#include <array>std::array<T, N> array_name;
T: 存储的元素类型 (例如 int, double, std::string)。
N: ...
网络层概述
网络层在OSI体系结构中是自下而上的第三层,其最核心的任务是将数据分组从源主机,经过多个网络和多段链路,最终传输到目的主机。这个核心任务可以被分解为两个关键功能:分组转发和路由选择
。
分组转发 (Forwarding)
当一台路由器从其某个接口所连接的链路上接收到一个数据分组后,它会根据分组首部中的信息,在自己的转发表中进行查询,并依据查询结果将该分组从一个合适的接口发...
排序算法是计算机科学中用于将一组数据按照特定顺序进行排列的算法。本节不讨论
C++ STL中的排序算法,而是介绍一些基本的排序算法及其实现。
对于当前的排序算法, 主要分为两大类: 1. 比较排序算法
(Comparison-based Sorting Algorithms):
这些算法通过比较元素之间的大小关系来决定它们的顺序。常见的比较排序算法包括快速排序
(Quick Sor...
可迭代对象 (Iterable)
是指那些能够逐一返回其内部成员的对象(返回迭代器)。换句话说,任何你可以用
for 循环进行遍历的对象,都是可迭代对象。
常见的可迭代对象
常见的可迭代对象包括:
序列 (Sequence):如列表 (list)、元组 (tuple)、字符串 (str)。
集合 (Set):如 set、frozenset。
映射 (Mapping):如字典...