AtomicIncrement using CompareAndSwap
AtomicIncrement using CompareAndSwap
不是家庭作业,为考试而学习。
我对问题陈述的最佳尝试:
假设一个线程调用 AtomicIncrement,传递指向共享整数变量的指针。没有指定另一个线程是否会修改此变量,但这是可能的。比较和交换的实现在成功交换时返回 1,在失败时返回 0(旧 != 值)
void AtomicIncrement(int *value, int amount) {
do { int old = *value; } // save old value
while (CompareAndSwap(value, old, old + amount) == 0);
}
问题:
我真的不明白这里发生了什么。
代码之所以做" int old = *value; "是因为另一个线程可能会在do {}和while条件检查之间更改(*值)吗?
我的教科书(第 10 页)说"反复尝试将值更新为新数量",但我看不出 *value 除了通过调用线程传递给 AtomicIncrement() 的原始值之外,我一定错过了一些东西。混淆来自于这样一个事实,即 CompareAndSwap 一开始应该是一个原子指令,所以在对 CompareAndSwap 的"调用"期间没有机会更改 *值。
如果没有临时变量或循环,您将运行CompareAndSwap(value, *value, *value + amount)
.这不是原子的。在评估函数的参数(计算每个参数之间没有确定顺序)和函数调用本身之间有一个序列点。
此函数必须加载*value
,以作为参数传递给CompareAndSwap
。它还必须加载*value
以用于表达式*value + account
,也作为参数传递。
问题 1.从这个线程加载*value
到它调用CompareAndSwap
,*value
可能已经被另一个线程更改了。这就是为什么循环是必要的。
问题 2.不能保证编译器只发出单个*value
负载。加载*value
一次并在本地将其amount
添加到其副本是合法的,但它加载*value
两次也是合法的,一次用于第二个参数,一次用于第三个参数。如果发生这种情况,则可能是另一个线程在这些负载之间更改了*value
。这就是使用临时变量的原因,尽管这实际上仍然不能保证没有内存屏障的单个加载。
- "using namespace std;"在C++的作用是什么?
- vector<vector<double>> to mxArray using memcpy
- Using C++ CryptAPI:CNG Create CSR
- STLPort using C++11
- 函数中的 c++ using 语句,后跟函数名称(对于 ADL?
- Using getchar_unlocked()
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- 为什么"using System;"不被视为不良做法?
- 为什么我需要做'using namespace std'而不是"使用 std::cout"?
- 'using namespace'实现细节的便捷方法(仅标头库)?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- 在"template"和函数声明之间使用:template<typename trait> using tr = base_trait<trait> void fn(tr::t
- 如何区分C++中的"using declaration"和"using directive"?
- C++ "using tcp=x"到"namespace tcp=x"有什么区别
- 如何为流输出运算符提供重载<<模板'using'类型别名?
- Using PrimitiveBatch::DrawIndexed with ID3D11DeviceContext::
- 如何创建一个 while 循环,继续循环,直到在C++中输入'using streams'键?
- 是否可以使用 using 将基类中的公共成员重新声明为派生类中的私有成员?
- AtomicIncrement using CompareAndSwap