我想我忽略了一些明显的东西。我有这样的代码:
int *a = <some_address>;
int *b = <another_address>;
// ...
// desired atomic swap of addresses a and b here
int *tmp = a;
a = b; b = tmp;
我想以原子的方式来做这件事。我一直在研究__c11_atomic_exchange
和OSX上的OSAtomic方法,但似乎没有一个方法能以原子的方式执行直接的交换。它们都能以原子的方式将一个值写入2个变量中的 1,但不能同时写入两个变量。
有什么想法吗
2条答案
按热度按时间njthzxwz1#
这取决于你的体系结构,什么是有效和高效的可能。在任何情况下,你都需要你想要交换的两个指针在内存中是相邻的,最简单的是你有他们一些像
然后,如果你有一个完整的C11编译器,你可以使用
_Atomic(pair)
作为一个原子类型来交换这样一个pair
的内容:首先将实际对加载到临时中,用交换的两个值构造一个新的对,进行比较交换以存储新值,并在必要时进行迭代:根据你的体系结构,这可能是实现一个 * 锁自由 * 原语操作或没有。现代64位体系结构通常有128位原子,这可能会导致一些128位汇编指令。
但这在很大程度上取决于您的平台上原子操作的实现质量。P99将为您提供一个实现原子操作的“类函数”部分的实现,并且在检测到时支持128位交换;在我的机器(64位Intel Linux)上,这有效地编译成
lock cmpxchg16b
指令。相关文件:
lo8azlld2#
快速总结:基于自旋锁原子交换应答
这个代码片段就是我们将要构建的内容。
对于多核系统上的基本自旋锁(高速,无上下文切换互斥)方法,这是自旋锁最好的地方,您可以像这样对变量值(在这种情况下是指针)进行原子交换:
详细信息如下:
C11中通用的自旋锁方法(用于 Package any 需要原子化的“critical section”)
如果您的架构支持使用in the main answer here提供的数组“pair”进行无锁原子交换,那么请考虑一下。它可能是无锁的,因此比使用互斥锁或自旋锁更有效。
我想更深入地研究这个问题,并尝试使用自旋锁。我已经 not speed分析了各种技术(数组“对”,互斥和自旋锁),但如果我这样做,看看它们在速度上的比较会非常有趣和学术。
不管怎样,就像我说的:你也可以使用互斥锁。
或者,如果你不想让线程在互斥体不能立即可用时进入睡眠状态,你可以通过使用旋转锁来提高效率,因为旋转锁必须旋转的次数通常很小,所以旋转锁比让线程进入睡眠状态并进行整个上下文切换要快。
C11有一整套的原子类型和函数,可以让你轻松地实现自己的自旋锁来实现这一点。
但是,请记住,基本的自旋锁不能在裸机(没有操作系统)单核(处理器)系统上使用,因为如果主上下文获取锁,然后当锁仍然被获取时,ISR触发并试图获取锁,这将导致死锁。ISR将无限期阻塞。
为了避免这种情况,必须使用更复杂的锁定机制,例如具有超时的自旋锁,如果锁被占用,则自动重新调度自己稍晚的时间的ISR,自动让步等。
因此,最好为具有操作系统和调度程序的多核系统保留旋转锁。
C11中
_Atomic
类型的基本自旋锁实现现在,您可以在您的多核系统中使用自旋锁,如下所示:
参考文献
1.*****C11并发支持库及
atomic_bool
等类型:https://en.cppreference.com/w/c/threadatomic_exchange()
功能:https://en.cppreference.com/w/c/atomic/atomic_exchange其他链接
1.请注意,您也可以使用C11的
struct atomic_flag
及其相应的atomic_flag_test_and_set()
函数,而不是像我上面所做的那样使用atomic_exchange()
创建自己的atomic_test_and_set()
函数。_Atomic
类型:https://en.cppreference.com/w/c/language/atomic<atomic>
待办事项
1.这个实现需要修改 * 添加安全防死锁机制,如自动延迟,超时和重试 *,以防止 * 单核和裸机 * 系统上的死锁。请参阅我的注解:Add basic mutex (lock) and spin lock implementations in C11, C++11, AVR, and STM32和这里:What are the various ways to disable and re-enable interrupts in STM32 microcontrollers in order to implement atomic access guards?