访问两个标量字段的原子性

6
在一个多线程 (Linux/amd64, Pthreads, C11) 应用程序中,我有一个结构体 (momitem_stmonimelt.h 中),其中包含两个字段。
uint16_t i_paylkind;
void* i_payload;

(如果需要,我可以将i_paylkind的类型更改为其他整数类型,例如uintptr_tatomic_uint
顺带一提,i_paylkind是一个鉴别标记,定义了i_payload所指向的实际结构体运行时类型。
是否可能原子地访问这两个字段(相对于访问同一struct的其他线程)。 当然,我在同一结构体中还有一个pthread_mutex_t i_mtx;,可以使用pthread_mutex_lock锁定。 但出于性能原因,我可能想要避免那样做(也许事务性内存可能与此有关)。
看起来<stdtomic.h>没有提供任何机制来实现这一点。
(与我的MELT monitor GPLv3+软件相关的问题)

1
我认为你需要硬件支持双比较交换操作,或者引入更高级别的锁(自旋锁、互斥锁,由你决定)。 - user703016
顺便提一下:pthread_mutex_t 通常是整数类型的 typedef。这通常不会默认带来巨大的性能损失。 - jim mcnamara
1
@ParkYoung-Bae,是的和不是的,你有任何你的编译器提供的适合的东西。例如,如果你的结构体具有适用于低级原子操作的大小,则您的编译器可以将其实现为这样。现代处理器通常具有128位原子指令,用于整个缓存行。但这不是应用程序员需要知道的。语言已经涵盖了这一点。(顺便说一下,gcc并没有使用自旋锁来实现这一点,而是使用互斥锁) - Jens Gustedt
@ParkYoung-Bae,如果可能的话,他想要这样做,编译器构造者知道这一点,然后他会这样做。但也许你可以让Basile自己决定,什么是对他的答案。 - Jens Gustedt
@Jens 这有什么不同于我最初的评论吗? - user703016
显示剩余4条评论
1个回答

4
如果您确实拥有C11编译器,那么_Atomic修饰符适用于任何数据类型。只需要使用它即可。对于struct类型,您可以执行的唯一操作是加载和存储,遗憾的是,您无法访问单个成员。

也许可以添加一个预处理器检查 #ifdef __STDC_NO_ATOMICS__ #error No atomic #endif?我认为 _Atomic 限定符不是必须实现的。 - Lundin
2
@Lundin,问题文本是在假设存在stdatomic.h的情况下制定的。在C11中,要么你拥有所有原子操作,包括_Atomic,要么就什么都没有。 - Jens Gustedt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接