C ++中的易失性11

在C ++ 11标准中,机器型号从单线程机器变为多线程机器。

这是否意味着典型的static int x; void func() { x = 0; while (x == 0) {} } static int x; void func() { x = 0; while (x == 0) {} } static int x; void func() { x = 0; while (x == 0) {} }优化出读的例子将不再发生在C ++ 11中?

编辑:对于那些不知道这个例子的人(我很惊讶),请阅读:https://en.wikipedia.org/wiki/Volatile_variable

EDIT2:OK,我真的很期待,大家谁知道volatile是已经看到了这个例子。

如果在示例中使用代码,则循环中的变量读取将被优化,从而使循环无限。

当然,解决方案是使用volatile来强制编译器在每次访问时读取变量。

我的问题是,如果这在C ++ 11中是一个不推荐的问题,因为机器模型是多线程的,因此编译器应该考虑对系统中存在的变量的并发访问。


它是否被优化完全取决于编译器以及他们选择优化的内容。 C ++ 98/03内存模型不能识别x在其设置和值的检索之间可能发生变化的可能性。

C ++ 11内存模型确实认识到x可能会改变。 但是,它并不关心。 非原子访问变量(即:不使用std::atomic或合适的互斥体)会产生未定义的行为。 因此,对于C ++ 11编译器来说,假设x在写入和读取之间不会发生变化是完全正确的,因为未定义的行为可能意味着“该函数永远不会看到x发生变化”。

现在,让我们看看C ++ 11对volatile int x;的看法volatile int x; 。 如果你把它放在那里,并且你有一些其他线程与x ,你仍然有未定义的行为。 易挥发不影响穿线行为。 C ++ 11的内存模型没有定义从xx读或写是原子的,也不需要为非原子读/写所需的内存屏障正确排序。 volatile与其无论如何都无关。

哦,你的代码可能工作。 但是C ++ 11并不能保证它。

什么是volatile告诉编译器,它不能优化该变量的内存读取。 但是,CPU内核具有不同的高速缓存,并且大多数内存写入不会立即发送到主内存。 它们被存储在该核心的本地缓存中,并可能最终被写入...。

CPU可以将缓存行强制到内存中,并同步不同内核之间的内存访问。 这些内存屏障允许两个线程进行有效通信。 仅仅从一个写在另一个核心上的内核中读取内存是不够的; 编写内存的核心需要发出一个障碍,而读取它的核心在读取数据之前需要完成该障碍。

volatile保证没有这个。 易失性与“硬件,映射的内存和东西”一起工作,因为写入该内存的硬件确保缓存问题得到处理。 如果CPU内核在每次写入后都发出内存障碍,那么基本上可以吻任何性能的希望了。 所以C ++ 11有特定的语言说什么时候需要构造才能发出障碍。

volatile是关于内存访问(何时读取); 线程是关于内存完整性(实际存储在那里的)。

C ++ 11内存模型特定于哪些操作会导致一个线程中的写入在另一个线程中可见。 这是关于内存完整性,这不是一些volatile句柄。 而内存完整性通常要求两个线程都做一些事情。

例如,如果线程A锁定一个互斥锁,执行写操作然后将其解锁,则C ++ 11内存模型只要求线程B稍后将其锁定就可以对线程B可见。 直到它实际获得该特定的锁定,它才有什么价值。 这些东西在标准的第1.10节中详细列出。

让我们看看你引用的代码,关于标准。 第1.10节提到某些库调用能够使线程与另一个线程“同步”。 大多数其他段落解释了同步(和其他事物)如何在线程之间建立操作的顺序。 当然,你的代码不会调用任何这些。 没有同步点,没有依赖顺序,什么也没有。

没有这种保护,没有某种形式的同步或排序,1.10 p21进来:

如果一个程序的执行包含一个数据争用,如果它包含两个不同线程中的冲突动作,其中至少有一个不是原子的,而且两个都不会发生在另一个线程之前。 任何这样的数据竞争都会导致未定义的行为。

您的程序包含两个冲突的操作(从x读取并写入x )。 它们都不是原子的,也不是通过同步来排序才会发生在另一个之前。

因此,你已经实现了未定义的行为。

因此,通过C ++ 11内存模型确保多线程行为的唯一情况是,如果您使用适当的原子加载/存储调用使用正确的互斥锁或std::atomic<int> x

哦,而且你也不需要让x变得不稳定。 无论何时调用(非内联)函数,该函数或其调用的某个函数都可以修改全局变量。 所以它不能优化while循环中的x的读取。 每个C ++ 11机制都需要调用一个函数。 这恰好会引发内存障碍。

链接地址: http://www.djcxy.com/p/26945.html

上一篇: Volatile in C++11

下一篇: c++