C ++中的易失性11

在C ++ 11标准中,机器型号从单线程机器变成了multithreading机器。

这是否意味着典型的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

编辑2:好的,我真的期待知道什么是volatile每个人都看过这个例子。

如果在示例中使用了代码,那么循环中读取的variables将被优化,从而使循环无止境。

当然,解决scheme是使用volatile来强制编译器读取每个访问上的variables。

我的问题是,如果在C ++ 11中这是一个不推荐的问题,因为机器模型是multithreading的,所以编译器应该考虑对系统中的variables进行并发访问。

它是否被优化完全取决于编译器和他们select优化的东西。 C ++ 98/03内存模型不能识别x可能在设置和值的检索之间改变的可能性。

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

现在,让我们来看看C ++ 11对volatile int x; 。 如果你把它放在那里,而且还有一些其他的线程与x混淆在一起, 你仍然有未定义的行为 。 易挥发不影响穿线行为。 C ++ 11的内存模型没有定义从xx读取或写入是primefaces的,也没有要求非primefaces读取/写入所需的内存屏障被正确sorting。 volatile与这种或volatile无关。

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

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

CPU有办法强制高速caching行进入内存,同步不同内核之间的内存访问。 这些内存屏障允许两个线程有​​效地进行通信。 仅仅从另外一个核心的内核中读取内存是不够的; 写内存的核心需要发出一个屏障,而读取它的核心在读取它之前需要有一个完整的屏障才能得到数据。

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

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

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

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

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

没有这样的保护,没有某种forms的同步或sorting,1.10 p21进来:

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

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

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

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

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