顺序性:
例如这几行代码,前面三行代码的赋值操作没有意义,cpu可能直接把代码有化成int ii=50
可见性:
原子操作:
例如i++,cpu执行这行代码分三个步骤
- 从内存中读取i的值
- 把i+1
- 把i的值写回内存
这三个步骤不是一气呵成,中间可能会被打断,例如某个线程在执行到其中一个步骤的时候,如果自己的CPU事件片用完了,就会被操作系统切换出去,当这个线程再次获得时间片的时候,黄花菜都凉了
在一台多核系统中,以下代码aa不会得到200w,如果在单核,则会得到200w
#include <iostream>
#include <thread> // 线程类头文件。
using namespace std;
int aa = 0; // 定义全局变量。
// 普通函数,把全局变量aa加1000000次。
void func() {
for (int ii = 1; ii <= 1000000; ii++)
aa++;
}
int main()
{
// 用普通函数创建线程。
thread t1(func); // 创建线程t1,把全局变量aa加1000000次。
thread t2(func); // 创建线程t2,把全局变量aa加1000000次。
t1.join(); // 回收线程t1的资源。
t2.join(); // 回收线程t2的资源。
cout << "aa=" << aa << endl; // 显示全局变量aa的值。
}
这是因为在多核系统中,每个线程可能被分配到不同的核心上执行,全局变量aa的读写可能会引发多个线程之间的竞争条件,导致结果不准确。
具体来说,在多核系统中,每个线程可能被分配到不同的核心上执行,当多个线程同时访问全局变量aa时,就会出现竞争条件。例如,线程1读取全局变量aa的值为10,线程2也读取全局变量aa的值为10,线程1增加aa的值为11,线程2也增加aa的值为11,最终全局变量aa的值只增加了1次,而不是2次。因此,最终的结果不是200w,而是小于200w的值。