C/C++编程:内存模型和数据竞争 我不是女神ヾ 2022-11-10 10:40 132阅读 0赞 # 内存模型 # * 内存模型为C++抽象机的目的定义了计算机内存存储的语义 * 可为C++程序所用的**内存是一或者多个字节的连续序列**。内存中的每个字节拥有唯一的肚子鼓 ## 字节 ## * **字节(byte)是最小的可寻址内存单元。它被定义为相接的位序列**,其大到足以保有任何 UTF-8 编码单元(256 个相异值)和 (C++14 起)基本执行字符集(96 个字符,要求必为单字节)的任何成员。与 C 相似,C++ 也支持 8 位或更大的字节。 * `char、unsigned char 和 signed char` 类型把一个字节用于存储和值表示。字节中的位数可作为 `CHAR_BIT`或 `std::numeric_limits<unsigned char>::digits` 访问。 ## 内存位置 ## 一个内存位置是: * 一个标量类型(算术类型、指针类型、枚举类型或 std::nullptr\_t)对象 * **非零长位域**的最大相接序列 struct S { char a; // 内存位置 #1 int b : 5; // 内存位置 #2 int c : 11, // 内存位置 #2 (延续) : 0, d : 8; // 内存位置 #3 struct { int ee : 8; // 内存位置 #4 } e; } obj; // 对象 'obj' 由 4 个分离的内存位置组成 ## 线程与数据竞争 ## * 执行线程是程序中的控制流,它始于`std::thread::thread`,`std::async`或以其他方式所进行的顶层函数调用 * 任何线程都能潜在的访问程序中的任何对象(拥有自动或线程局部存储期的对象仍然可以被另一线程通过指针或引用访问) * 不同的执行线程始终可以同时访问(读和写)不同的内存位置,不需要干涉或同步的任何要求。 当某个表达式的求值写入某个内存位置,而另一求值读或修改同一内存位置时,称这些表达式冲突。拥有两个冲突的求值的程序就有数据竞争,除非 * 两个求值都在同一线程上,或者在同一`信号处理函数`中执行 * 两个冲突的求值都是原子操作(见 `std::atomic` ) * 一个冲突的求值发生早于(happens-before)另一个(见`std::memory_order`) 如果出现数据竞争,则程序行为未定义 int cnt = 0; auto f = [&]{ cnt++;}; std::thread t1{ f}, t2{ f}, t3{ f}; // 未定义行为 std::atomic<int> cnt{ 0}; auto f = [&]{ cnt++;}; std::thread t1{ f}, t2{ f}, t3{ f}; // OK ## 内存顺序 ## * 当线程从某个内存位置读取值时,它可能看到初值,同一线程所写入的值,或者另一线程所写入的值。 * 有关线程所作的写入操作对其他线程变为可见的顺序上的细节,见`std::memory_order`
还没有评论,来说两句吧...