如下所示,我有一个结构体,它有几个位域。我还有一个包含volatile 64位值和此结构的联合。通过联合访问的结构的更改是否也是易失性的?
也就是说,由于结构体和volatile int共享相同的内存位置,对结构体的访问是否也会导致每次访问都访问内存,或者编译器会将它们存储在寄存器中?
typedef struct {
uint64 my_info_1:12;
uint64 my_info_2:16;
uint64 reserved: 36;
} my_info_s;
typedef union {
my_info_s my_info_struct;
volatile unsigned long long my_info_vol; //64 bit
} my_info_u;
my_info_u my_info;
//Are these volatile accesses?
my_info.my_info_1 = 4;
my_info.my_info_2 = 8;
//This is the motivation- update a bunch of bitfields, but set them in one shot.
atomic_set(atomic_location, my_info.my_info_vol);
由于一些实时约束,我不能使用锁/互斥来实现这一点。
2条答案
按热度按时间nom7f22z1#
好吧,正如我所看到的,您最初的问题可以改为“volatile是线程安全的等价物吗”。可悲的答案是“不”。
对于多线程代码,有两个主要的敌人:
1.编译器级优化。这一个可以被“易失性”分类器击败。(是的,它肯定只是损坏的编译器,优化volatile变量作为寄存器-然后,用正确的编译器(如GCC或CLang)更改编译器)
毕竟,一旦你不能使用锁和互斥锁,似乎你正在寻找所谓的“无锁编程”。看看Andrei Alexandrescu的Lock-Free Data Structures或这个Introduction to Lock-Free Programming
p4tfgftt2#
我不知道官方标准是怎么说的,但让我们从逻辑上思考一下:
联合
volatile 64位类型只是联合的一个选项。如果“每个人都同意”将工会解释为非易失性类型,那么就好像这个选项不存在一样--除了在规模方面。所以我想说你们的结合并不是天生的不稳定。
不过,我建议你:**永远不要将volatile和nonvolatile成员放在同一个联盟中。**这样做只会带来麻烦、混乱和bug。
结构体
如果成员是易失性的,即如果它的内容可以在当前执行线程的读取之间被修改,则根据定义,对于包含它的任何结构都是如此,它的内容(尽管可能只是其中的一些)也可以因此被修改。所以有volatile成员的结构体本身也是volatile的。