Dan*_*son 6 language-agnostic multithreading atomic lock-free
我遇到了需要内存中两个值的原子总和的情况.我继承的代码是这样的:
int a = *MemoryLocationOne;
memory_fence();
int b = *MemoryLocationTwo;
return (a + b) == 0;
Run Code Online (Sandbox Code Playgroud)
a和b的单独读取都是原子的,并且代码中其他位置写入这两个内存位置的所有内容也是无锁原子的.然而,问题在于两个位置的值可以并且确实在两个读取之间改变.
那么如何使这个操作成为原子?我知道关于CAS的所有内容,但它往往只涉及使读取 - 修改 - 写入操作原子化,这不是我想要做的.
有没有办法做到这一点,或者是重构代码的最佳选择,这样我只需要检查一个值?
编辑:谢谢,我没有提到我想在第一次修订中无锁地执行此操作,但有些人在我的第二次修订后接受了它.我知道当他们说这样的话时没有人相信人,但我实际上不能使用锁.我必须使用原子来模拟一个互斥体,这比重构代码以跟踪一个值而不是两个值更有用.
目前我的调查方法涉及利用这些值是连续的这一事实,并使用64位读取原子地抓取它们,我确信这些目标平台上是原子的.如果有人有新想法,请捐款!谢谢.
如果您确实需要确保在进行此测试时不进行更改,那么您需要对a
和的所有访问使用相同的同步。这是你唯一的选择。对这些值中的任何一个的每次读取和每次写入都需要使用相同的内存栅栏、同步器、信号量、时间片锁或任何使用的机制。b
a
b
有了这个,您可以确保:
memory_fence_start();
int a = *MemoryLocationOne;
int b = *MemoryLocationTwo;
int test = (a + b) == 0;
memory_fence_stop();
return test;
Run Code Online (Sandbox Code Playgroud)
然后a
在您阅读时不会改变b
。但同样,您必须对所有a
对 和 的访问使用相同的同步机制b
。
为了反映您正在寻找一种无锁方法的问题的后续编辑,这完全取决于您正在使用的处理器以及 和 的长度a
以及b
这些内存位置是否连续且正确对齐。
假设这些在内存中是连续的,并且每个都是 32 位,并且您的处理器具有原子 64 位读取,那么您可以发出原子 64 位读取来读取这两个值,从 64 位值中解析这两个值,进行数学计算并返回您想要返回的内容。a
假设您永远不需要对“同时”进行原子更新,而只需要对“ ”或“ ”进行b
原子更新,那么这将在没有锁的情况下完成您想要的操作。a
b