【问题标题】:`pthread_mutex_t`, `sem_t` in a `std::map``std::map` 中的`pthread_mutex_t`、`sem_t`
【发布时间】:2013-05-16 12:05:18
【问题描述】:

基本上我为一堆对象维护一组状态:

#define SUBSCRIPTION_TYPE int
std::map< SUBSCRIPTION_TYPE , bool > is_object_valid;

我需要用各自的mutex_t(而不是大锁)保护is_object_valid 中的每个元素。由于SUBSCRIPTION_TYPE 的有效值是稀疏(例如,从 0 到 10000000 的几十个值),std::map 优于 std::vector、C 样式数组等。

我正在尝试实现以下目标:

std::map< SUBSCRIPTION_TYPE , pthread_mutex_t > mutex_array;

但它似乎不起作用。 (嗯,std::map 更新时可能会发生数据竞争)。

那么实现这一目标的最佳方法是什么?我必须编写一个线程安全的订阅分配器,将SUBSCRIPTION_TYPE 映射为连续整数,以便我可以将mutex_ts 存储在一个数组中吗?

【问题讨论】:

  • 全地图锁定有什么问题?
  • @zch 呃,效率不够。程序的一部分依赖于远程过程调用,因此不必要地阻塞多个线程太昂贵了。
  • 您没有显示足够的代码来进行真正的诊断,但我有一些猜测:当您将互斥锁“插入”到地图中时,您实际上是在创建一个新的互斥锁。所以你需要初始化它并锁定它。您从中复制的互斥锁现在没用了。因此,请确保您有时不会锁定原件,有时会锁定地图中的那个。
  • @WanderingLogic 他应该能够推迟初始化地图中的互斥锁,直到它实际在地图中。 std::pair&lt;Map::iterator, bool&gt; r = myMap.insert( make_pair&lt;int, pthread_mutex_t&gt;( newKey, pthread_mutex_t() ) ); assert( r.second ); pthread_mutex_init( &amp;r.first-&gt;second, NULL ); 之类的东西当然,他必须在整个序列中保持地图上的全局锁定。

标签: c++ concurrency stl pthreads


【解决方案1】:

如果任何线程正在修改地图本身(插入等),您 需要保护对地图的所有访问。之后:如果 会员只是一个bool,你能做多少处理 它将这个时间添加到地图级别互斥锁的持有时间 会改变任何事情。

否则:如果您需要每个对象的互斥锁,简单的解决方案 将它们放入与地图上相同的对象中。 但它mutex_t 可复制吗? pthread_mutex_tstd::mutex 不是。这可能会使插入代码过于复杂, 因为你不能初始化pthread_mutex_t,或者构造 std::mutex,在插入对象之前。 (在 C++11 中,你 可以使用emplace来解决这个问题;地图的内容 如果您使用 emplace,则不必是可复制的。)在 C++03 中, 但是,您必须将分配与初始化分开; struct 包含您的映射值,互斥锁将 实际上必须使用互斥体的原始内存声明,并且 然后放置 new 用于使用您的迭代器对其进行初始化 从insert回来。

【讨论】:

    【解决方案2】:

    如果您有多个线程读写mutex_array,则需要另一个互斥锁来保护它。

    您确定会有多个线程写入mutex_array吗?

    另一件事是,你可以有一个map&lt;subscription_type, object_struct&gt;,而不是两个地图

    struct object_struct {
       bool valid;
       pthread_mutex_t mutex;
    };
    

    然后有一个单独的弧形互斥锁来保护该映射。

    【讨论】:

    • 一旦有多个线程访问映射,并且至少有一个正在写入,所有线程都需要保护访问。
    • 当然还有:他不能在互斥体上调用pthread_mutex_init,直到它在映射中实际到位。 (至少根据 Posix。如果 使用默认值初始化互斥锁,我很难相信只要你没有,总是复制 pthread_mutex_t initializer = PTHREAD_MUTEX_INITIALIZER; 是行不通的在插入之前不要尝试使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多