根据en.cppreference.com的说法,std::atomic_exchange和std::atomic_store相当于线程安全的std::swap.但这不是我在g++或clang++上得到的行为。
问题就在科鲁身上。 (见下文)
不过,它会打印这个:
std::atomic_store
a: 0x1ed2c30 0
b: 0x1ed2c50 1
a: 0x1ed2c50 1
b: 0x1ed2c50 1
std::atomic_exchange
a: 0x1ed2c50 0
b: 0x1ed2c30 1
a: 0x1ed2c30 1
b: 0x1ed2c30 1为什么会这样呢?我做错了什么吗?我看错文件了吗?
代码列表
#include <iostream>
#include <memory>
int main()
{
{
std::cout << "std::atomic_store\n\n";
auto a = std::make_shared<int>(0);
auto b = std::make_shared<int>(1);
std::cout
<< "a: " << a.get() << '\t' << *a << '\n'
<< "b: " << b.get() << '\t' << *b << '\n' << std::endl;
std::atomic_store(&a, b);
std::cout
<< "a: " << a.get() << '\t' << *a << '\n'
<< "b: " << b.get() << '\t' << *b << '\n' << std::endl;
}
{
std::cout << "std::atomic_exchange\n\n";
auto a = std::make_shared<int>(0);
auto b = std::make_shared<int>(1);
std::cout
<< "a: " << a.get() << '\t' << *a << '\n'
<< "b: " << b.get() << '\t' << *b << '\n' << std::endl;
std::atomic_exchange(&a, b);
std::cout
<< "a: " << a.get() << '\t' << *a << '\n'
<< "b: " << b.get() << '\t' << *b << '\n' << std::endl;
}
}发布于 2016-01-28 22:25:43
这种描述有点误导人。
上面写着,例如,
template<class T>
void atomic_store( std::shared_ptr<T>* p,
std::shared_ptr<T> r );“有效”做p->swap(r)。从它得到的角度来看,这是正确的(实际上,标准也是这么说的)。
但是,r是一个由值传递的函数参数,因此在函数返回之前被销毁。它不会影响来电者的任何事情。
发布于 2016-01-28 22:23:21
std::atomic_exchange不交换a和b,它将a设置为b并返回a的前一个值。
你可以这样做:
b = std::atomic_exchange(&a, b);这将如您所期望的那样工作(交换a和b的指针),但这不是线程安全的:如果多个线程同时访问对象b,则这是未定义的行为。您不能做得更好,因为共享指针是一个复杂的结构,通常包含两个数据成员(两个指针)。由于原子无锁交换需要硬件支持,这只适用于基本类型(整数和指针)。
发布于 2016-01-28 22:20:31
很久以来,我一直很困惑为什么“比较和交换”中有swap。它不能交换任何东西。如果,它将设置值,如果检查失败,则返回当前值。因此,atomic_exchange绝不等同于std::swap。
相反,它是一种检查和设置模式,所以我总是更喜欢CAS,而不是表示比较集。
https://stackoverflow.com/questions/35073200
复制相似问题