正在访问指针元组的元组和线程安全的互斥锁
Is accessing a tuple of tuples of pointers and a mutexes thread-safe
鉴于 std::tuple
,
using Tuple1 = std::tuple<Foo1*, Bar1*, std::shared_ptr<std::mutex>>;
using Tuple2 = std::tuple<Foo2*, Bar2*, std::shared_ptr<std::mutex>>;
std::tuple<Tuple1, Tuple2> tuple;
和函数,
void baz()
{
auto tup = std::get<0>(tuple);
std::lock_guard<std::mutex> lk(*std::get<2>(tup));
// Do something with std::get<0>(tup) and std::get<1>(tup)
}
根据 关于 SO 的问题,访问 std::tuple
本质上不是线程安全的,但是在示例代码的情况下呢? undefined/strange 事情有可能发生吗?
这是假设 FooN
& BarN
仅在锁定后访问。
引用您所链接问题的完美答案:
However, if the parameter were const, then get would not be considered to provoke a data race with other const calls to get.
这基本上就是您的答案。 在 const
元组上进行每个 get
调用(在任何未 完全 受互斥锁保护的元组上),你就安全了.
这意味着您发布的代码不安全。修改如下:
void baz()
{
// vvvv just being explicit here
auto const & tup = std::get<0>(static_cast<decltype(tuple) const &>(tuple));
std::lock_guard<std::mutex> lk(*std::get<2>(tup));
// Dereference std::get<0>(tup) and std::get<1>(tup),
// use the pointed to objects at will, nothing else
// Not ok, because it could interfer with the call in initialisation of tup of another thread
// auto non_const_tup = std::get<0>(tuple)
}
目前我看到的唯一解决方案是使用像这样的元组:
std::tuple<
std::shared_pointer<std::mutex>,
std::unique_pointer<std::tuple<Foo1*, Bar1*>>
// Mutex and pointer to tuple for Foo2 and Bar2
>
所需的 const
将坚持所有内容(指针目标除外)。
鉴于 std::tuple
,
using Tuple1 = std::tuple<Foo1*, Bar1*, std::shared_ptr<std::mutex>>;
using Tuple2 = std::tuple<Foo2*, Bar2*, std::shared_ptr<std::mutex>>;
std::tuple<Tuple1, Tuple2> tuple;
和函数,
void baz()
{
auto tup = std::get<0>(tuple);
std::lock_guard<std::mutex> lk(*std::get<2>(tup));
// Do something with std::get<0>(tup) and std::get<1>(tup)
}
根据 std::tuple
本质上不是线程安全的,但是在示例代码的情况下呢? undefined/strange 事情有可能发生吗?
这是假设 FooN
& BarN
仅在锁定后访问。
引用您所链接问题的完美答案:
However, if the parameter were const, then get would not be considered to provoke a data race with other const calls to get.
这基本上就是您的答案。 在 const
元组上进行每个 get
调用(在任何未 完全 受互斥锁保护的元组上),你就安全了.
这意味着您发布的代码不安全。修改如下:
void baz()
{
// vvvv just being explicit here
auto const & tup = std::get<0>(static_cast<decltype(tuple) const &>(tuple));
std::lock_guard<std::mutex> lk(*std::get<2>(tup));
// Dereference std::get<0>(tup) and std::get<1>(tup),
// use the pointed to objects at will, nothing else
// Not ok, because it could interfer with the call in initialisation of tup of another thread
// auto non_const_tup = std::get<0>(tuple)
}
目前我看到的唯一解决方案是使用像这样的元组:
std::tuple<
std::shared_pointer<std::mutex>,
std::unique_pointer<std::tuple<Foo1*, Bar1*>>
// Mutex and pointer to tuple for Foo2 and Bar2
>
所需的 const
将坚持所有内容(指针目标除外)。