fetch_mult 的这个原子实现是否正确?
Is this atomic implementation of fetch_mult correct?
This site 解释了 C++11 原子并给出了默认 std::atomic<T>
类型未提供的原子 fetch_mult
操作的示例实现:
#include <atomic>
#include <iostream>
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
T oldValue= shared.load();
// 1
while (!shared.compare_exchange_strong(oldValue, oldValue * mult));
return oldValue;
}
int main(){
std::atomic<int> myInt{5};
std::cout << myInt << std::endl;
fetch_mult(myInt,5);
std::cout << myInt << std::endl;
}
我无法理解这个函数。如果 fetch_mult
在点 // 1
被另一个也调用 fetch_mult
的线程中断,那么其中一个线程不会死锁,因为 compare_exchange_strong
永远不会 return true
除非 mult==1
或另一个线程将值设置回 oldValue
?
例如(T1 和 T2 是各自的线程):
- T1:
oldValue = 5;
- T2:
oldValue = 5;
- T2:
compare_exchange_strong
成功将值设置为25
- T1:
compare_exchange_strong
从未成功完成,因为它的 oldValue
仍然是 5
,除非 其他人 将值设置为 5
再次
我的理解对吗?如果是这样,这是否是 fetch_mult
的正确实施?
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
while (true) {
T oldValue = shared.load();
if (shared.compare_exchange_strong(oldValue, oldValue * mult))
return oldValue;
}
}
如果比较失败,atomic::compare_exchange_*
将当前值加载到 'expected' 参数中。在您的示例中,在步骤 4 中,T1 将使比较交换失败并将 25 加载到 oldValue
,然后在下一次迭代中成功。
This site 解释了 C++11 原子并给出了默认 std::atomic<T>
类型未提供的原子 fetch_mult
操作的示例实现:
#include <atomic>
#include <iostream>
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
T oldValue= shared.load();
// 1
while (!shared.compare_exchange_strong(oldValue, oldValue * mult));
return oldValue;
}
int main(){
std::atomic<int> myInt{5};
std::cout << myInt << std::endl;
fetch_mult(myInt,5);
std::cout << myInt << std::endl;
}
我无法理解这个函数。如果 fetch_mult
在点 // 1
被另一个也调用 fetch_mult
的线程中断,那么其中一个线程不会死锁,因为 compare_exchange_strong
永远不会 return true
除非 mult==1
或另一个线程将值设置回 oldValue
?
例如(T1 和 T2 是各自的线程):
- T1:
oldValue = 5;
- T2:
oldValue = 5;
- T2:
compare_exchange_strong
成功将值设置为25
- T1:
compare_exchange_strong
从未成功完成,因为它的oldValue
仍然是5
,除非 其他人 将值设置为5
再次
我的理解对吗?如果是这样,这是否是 fetch_mult
的正确实施?
template <typename T>
T fetch_mult(std::atomic<T>& shared, T mult){
while (true) {
T oldValue = shared.load();
if (shared.compare_exchange_strong(oldValue, oldValue * mult))
return oldValue;
}
}
atomic::compare_exchange_*
将当前值加载到 'expected' 参数中。在您的示例中,在步骤 4 中,T1 将使比较交换失败并将 25 加载到 oldValue
,然后在下一次迭代中成功。