C++ 原子的这种用法正确吗?
我有以下层次结构:C++ 原子的这种用法正确吗?,c++,multithreading,locking,atomic,C++,Multithreading,Locking,Atomic,我有以下层次结构: struct Point { std::atomic<int> x; std::atomic<int> y; std::atomic<int> z; } class Data { std::atomic<int> version; Point point; } unordered_map<std::string,Data> hashtable; // global 线程2执行以下操作: int
struct Point
{
std::atomic<int> x;
std::atomic<int> y;
std::atomic<int> z;
}
class Data
{
std::atomic<int> version;
Point point;
}
unordered_map<std::string,Data> hashtable; // global
线程2执行以下操作:
int local_version;
while(local_version!=shared_hashtable["string1"].version.load(memory_order_acquire))
{
//...process data...
local_version=shared_hashtable["string1"].version.load(memory_order_acquire);
}
传递的内存顺序是否保证我的存储和加载不会被重新排序。
设计是否按预期工作:如果更新了
hastable[“string1”]
上的对象,我会在线程2中处理相应的数据吗?hashtable
不受同时访问的保护,并且它的操作符[]
不是const
。如果您保证(1)hashtable[“string1”]
在这两个线程尝试访问它之前插入到表中,并且(2)在这两个线程运行期间没有其他线程写入hashtable
,则hashtable
中的查找不会导致数据争用。如果不能保证(1)和(2),则需要使用互斥锁来保护查找unordered_map
在迭代器重新灰化时使迭代器无效,但引用将保持有效,直到引用项从映射中删除
内存模型保证在线程2从memory\u order\u acquire
读取相应值后,线程1中内存\u order\u release
写入版本
之前的写入操作对线程2可见。即使对点
成员的访问是非原子的,情况也是如此
但是,线程2中点
成员的读取可能会看到线程1中稍后写入的值,因此不能保证线程2中读取的三个点
成员对应于线程1实际写入的特定点
。我想您需要保证线程2处理的点
实际上是线程1编写的某个点
,而不是多个不同点的值的集合(例如,版本1中的x
,版本2中的y
,版本3中的z
)。将设计从
struct Point { atomic<int> x, y, x; };
hashtable
不受同时访问的保护,其运算符[]
不是const
。如果您保证(1)hashtable[“string1”]
在这两个线程尝试访问它之前插入到表中,并且(2)在这两个线程运行期间没有其他线程写入hashtable
,则hashtable
中的查找不会导致数据争用。如果不能保证(1)和(2),则需要使用互斥锁来保护查找unordered_map
在迭代器重新灰化时使迭代器无效,但引用将保持有效,直到引用项从映射中删除
内存模型保证在线程2从memory\u order\u acquire
读取相应值后,线程1中内存\u order\u release
写入版本
之前的写入操作对线程2可见。即使对点
成员的访问是非原子的,情况也是如此
但是,线程2中点
成员的读取可能会看到线程1中稍后写入的值,因此不能保证线程2中读取的三个点
成员对应于线程1实际写入的特定点
。我想您需要保证线程2处理的点
实际上是线程1编写的某个点
,而不是多个不同点的值的集合(例如,版本1中的x
,版本2中的y
,版本3中的z
)。将设计从
struct Point { atomic<int> x, y, x; };
hashtable
不受同时访问的保护,其运算符[]
不是const
。如果您保证(1)hashtable[“string1”]
在这两个线程尝试访问它之前插入到表中,并且(2)在这两个线程运行期间没有其他线程写入hashtable
,则hashtable
中的查找不会导致数据争用。如果不能保证(1)和(2),则需要使用互斥锁来保护查找unordered_map
在迭代器重新灰化时使迭代器无效,但引用将保持有效,直到引用项从映射中删除
内存模型保证在线程2从memory\u order\u acquire
读取相应值后,线程1中内存\u order\u release
写入版本
之前的写入操作对线程2可见。即使对点
成员的访问是非原子的,情况也是如此
但是,线程2中点
成员的读取可能会看到线程1中稍后写入的值,因此不能保证线程2中读取的三个点
成员对应于线程1实际写入的特定点
。我想您需要保证线程2处理的点
实际上是线程1编写的某个点
,而不是多个不同点的值的集合(例如,版本1中的x
,版本2中的y
,版本3中的z
)。将设计从
struct Point { atomic<int> x, y, x; };
hashtable
不受同时访问的保护,其运算符[]
不是const
。如果您保证(1)hashtable[“string1”]
在这两个线程尝试访问它之前插入到表中,并且(2)在这两个线程运行期间没有其他线程写入hashtable
,则hashtable
中的查找不会导致数据争用。如果不能保证(1)和(2),则需要使用互斥锁来保护查找unordered_map
在迭代器重新灰化时使迭代器无效,但引用将保持有效,直到从中删除引用的项
struct Point
{
int x, y, z;
};
struct Data
{
std::atomic<int> version;
std::atomic<Point> point;
};
std::unordered_map<std::string, Data> hashtable;
std::mutex mtx;
Data& lookup(const std::string& key) {
std::lock_guard<std::mutex> guard{mtx};
return hashtable[key];
}
void thread1() {
std::string key;
Point point;
std::tie(key, point) = // get new key/point pair
auto& ref = lookup(key);
ref.point.store(point, std::memory_order_relaxed);
ref.version.fetch_add(1, std::memory_order_release);
}
void thread2() {
auto& ref = lookup("string1");
int local_version = 0;
for (;;) {
auto const version = ref.version.load(std::memory_order_acquire);
if (local_version != version) {
auto point = ref.point.load(std::memory_order_relaxed);
if (version == ref.version.load(std::memory_order_acquire)) {
local_version = version;
// ...process point...
}
}
}
}