C++ 所有数据访问都需要使用volatile修饰的多线程吗?

C++ 所有数据访问都需要使用volatile修饰的多线程吗?,c++,C++,对于原始人,我认为这是必要的。 即使对于非原语,例如数组,我认为它也是必要的。 无挥发性: int d[2]; 线程1: while (d[1] > 0) modify(d[0]); 线程2: while (d[0] > 0) modify(d[1]); 我担心编译器在没有volatile的情况下会如下更改我的代码。 while(true)modify() 所以我把volatile放在int d[2]之前; 但是我觉得用volatile装饰的东西有点奇怪。不,volatile不

对于原始人,我认为这是必要的。 即使对于非原语,例如数组,我认为它也是必要的。

无挥发性:

int d[2];
线程1:

while (d[1] > 0) modify(d[0]);
线程2:

while (d[0] > 0) modify(d[1]);
我担心编译器在没有volatile的情况下会如下更改我的代码。 while(true)modify()

所以我把volatile放在int d[2]之前;
但是我觉得用volatile装饰的东西有点奇怪。

不,volatile不是用来做这个的。Volatile用于可能在程序外更改的变量,例如内存映射设备、图形内存等


仅仅因为程序是多线程的,它就没有必要了——既不适用于基元类型,也不适用于数组。

不,volatile不适用于此。Volatile用于可能在程序外更改的变量,例如内存映射设备、图形内存等


仅仅因为程序是多线程的,它就没有必要了——既不适用于基元类型,也不适用于数组。

否。Volatile适用于在编译器不知道的情况下读取和/或写入的变量。虽然另一个线程更改变量可能会出现这种情况,
volatile
对于多线程编程来说是不够的,实际上也不需要

除非您自己编写同步原语,但这比看起来要困难得多。这似乎已经够难了


有关更多详细信息,请阅读有关此问题的Linux insight,网址为。这篇文章是针对C,而不是C++,但原理相同。

< P>不。Valor是指变量,这些变量可以在没有编译器知道的情况下被读取和/或写入。虽然另一个线程更改变量可能会出现这种情况,
volatile
对于多线程编程来说是不够的,实际上也不需要

除非您自己编写同步原语,但这比看起来要困难得多。这似乎已经够难了


有关更多详细信息,请阅读有关此问题的Linux insight,网址为。本文是针对C,而不是C++,但原理相同。

在这里,有两个线程是“修改彼此的数据”,这确实需要编译器知道数据是由另一个线程修改的。有几种解决方案,
volatile
会告诉编译器它无法将第一次读取的值存储在寄存器中,但这有问题

最重要的是,
volatile
无法解决在更改
d[1]>0
时精确检测“边缘”的问题,因为使用
volatile
,可以保证编译器不会删除对变量的读取。在具有多个内核的系统中,线程1中的新数据到达线程2之间很可能存在“延迟”。这意味着
d[0]
的修改次数可能比您预期的要多,因为循环运行了几个额外的周期。在极端情况下,例如某些型号的ARM处理器,循环可能或多或少地无限期运行,因为处理器(核心)将需要刷新缓存线,除非有其他东西使用相同的缓存线,否则这不会在没有干预的情况下发生。在一个不繁忙的系统中,这可能需要您所拥有的时间,或者更长的时间……;)

因此,我不同意在多线程环境中不需要
volatile
,但我同意这不是整个解决方案。如果检测值“立即”改变,则需要使用std::atomic和其他类似结构来确保正确性,以使代码正常工作


跨线程共享数据是一件困难的事情,需要仔细规划和理解才能使其正常工作。我知道上面的代码可能只是一个简化的示例,但是如果
modify(d[1])
是微不足道的,那么共享数据的情况将非常糟糕,而且它作为两个线程的运行速度可能比作为单线程循环的运行速度慢得多,因为一个处理器写入的每个缓存线都会强制刷新另一个处理器上的缓存线。因此,这就像在繁忙的曼哈顿交通中驾驶法拉利跑车——不是很节能,也不比简单的解决方案快多少

在这种情况下,有两个线程正在“修改彼此的数据”,这确实需要编译器知道数据正在被另一个线程修改。有几种解决方案,
volatile
会告诉编译器它无法将第一次读取的值存储在寄存器中,但这有问题

最重要的是,
volatile
无法解决在更改
d[1]>0
时精确检测“边缘”的问题,因为使用
volatile
,可以保证编译器不会删除对变量的读取。在具有多个内核的系统中,线程1中的新数据到达线程2之间很可能存在“延迟”。这意味着
d[0]
的修改次数可能比您预期的要多,因为循环运行了几个额外的周期。在极端情况下,例如某些型号的ARM处理器,循环可能或多或少地无限期运行,因为处理器(核心)将需要刷新缓存线,除非有其他东西使用相同的缓存线,否则这不会在没有干预的情况下发生。在一个不繁忙的系统中,这可能需要您所拥有的时间,或者更长的时间……;)

因此,我不同意在多线程环境中不需要
volatile
,但我同意这不是整个解决方案。如果检测值“立即”改变,则需要使用std::atomic和其他类似结构来确保正确性,以使代码正常工作