std::map<int, std::bitset<256 > > 线程安全 w/o 互斥?
std::map<int, std::bitset<256 > > thread safety w/o mutex?
我有一个
std::map<int, std::bitset<256 > > m;
构建完成后,不会插入新密钥,也不会删除任何密钥。我可以在不使用互斥锁的情况下在一个线程中安全地分配位集,同时在其他线程中读取它吗?
// thread 1:
std::bitset<256> a = getBitset();
m[1] = a;
// thread 2:
std::bitset<256> b = m[1];
// or alternatively
std::bitset<256> c = m.at(1);
我认为程序不会崩溃,但位集中可能会发生数据竞争。如果读取将提供新旧位集的组合,则数据竞争是可以接受的。
不,这不安全。
bitset
的 operator=
是一个修改操作,因此如果 bitset
在另一个线程中同时访问,则不能保证没有数据竞争。实际上,它几乎肯定会导致数据竞争,因为它需要写入对象。这并非特定于 std::bitset
,但几乎所有 non-empty non-atomic 标准库类型(以及大多数其他 non-empty 类型)通常都是如此。
任何数据竞争都会导致未定义的行为。没有部分更新。从这个意义上说,它永远不应该被接受。
如果您希望能够执行此操作,请将 bitset
包装在 struct
和 mutex
中以保护对 bitset
的访问,或者使用类似于 atomic shared_ptr
的东西,允许以原子方式将旧 bitset
与新 bitset
交换,并延迟销毁旧 shared_ptr
直到所有引用都消失。
虽然我认为不能保证,但 std::bitset
也可能是可复制的。您可以使用 std::is_trivially_copyable_v
上的 static_assert
进行检查,如果 true
,您还可以使用 std::atomic
or std::atomic_ref
,这将允许以原子方式访问位集(即没有数据竞争)并且只有当底层架构不支持对相应大小的对象进行原子访问时,才可能使用锁。
另请注意,std::bitset b = m[1];
和m[1]
也会导致未定义的行为,因为std::map
的operator[]
也是修改操作,未指定免于数据竞争,即使它没有在地图中插入新元素。您需要使用例如find()
成员函数。
我有一个
std::map<int, std::bitset<256 > > m;
构建完成后,不会插入新密钥,也不会删除任何密钥。我可以在不使用互斥锁的情况下在一个线程中安全地分配位集,同时在其他线程中读取它吗?
// thread 1:
std::bitset<256> a = getBitset();
m[1] = a;
// thread 2:
std::bitset<256> b = m[1];
// or alternatively
std::bitset<256> c = m.at(1);
我认为程序不会崩溃,但位集中可能会发生数据竞争。如果读取将提供新旧位集的组合,则数据竞争是可以接受的。
不,这不安全。
bitset
的 operator=
是一个修改操作,因此如果 bitset
在另一个线程中同时访问,则不能保证没有数据竞争。实际上,它几乎肯定会导致数据竞争,因为它需要写入对象。这并非特定于 std::bitset
,但几乎所有 non-empty non-atomic 标准库类型(以及大多数其他 non-empty 类型)通常都是如此。
任何数据竞争都会导致未定义的行为。没有部分更新。从这个意义上说,它永远不应该被接受。
如果您希望能够执行此操作,请将 bitset
包装在 struct
和 mutex
中以保护对 bitset
的访问,或者使用类似于 atomic shared_ptr
的东西,允许以原子方式将旧 bitset
与新 bitset
交换,并延迟销毁旧 shared_ptr
直到所有引用都消失。
虽然我认为不能保证,但 std::bitset
也可能是可复制的。您可以使用 std::is_trivially_copyable_v
上的 static_assert
进行检查,如果 true
,您还可以使用 std::atomic
or std::atomic_ref
,这将允许以原子方式访问位集(即没有数据竞争)并且只有当底层架构不支持对相应大小的对象进行原子访问时,才可能使用锁。
另请注意,std::bitset b = m[1];
和m[1]
也会导致未定义的行为,因为std::map
的operator[]
也是修改操作,未指定免于数据竞争,即使它没有在地图中插入新元素。您需要使用例如find()
成员函数。