【问题标题】:Mutex map data structure互斥映射数据结构
【发布时间】:2013-05-10 22:19:52
【问题描述】:

问题

  • 我有一个目录 D,我想将 (K, V) 对放入其中
  • void save(K, V) 将文件名 K 和内容 V 保存到目录 D
    • 具有“即发即弃”语义 - 函数可能会在实际将文件保存到磁盘之前返回
  • 目录D 是类C 定义save 函数的字段
  • 对void save(K, V) 的调用应该同时运行
    • 使用tbb::task 进行并发
    • 不能同时运行对同一密钥的两次文件写入
    • 也就是说,如果两个线程同时调用save(K, V1)和save(K, V2),结果应该是D中一个名为K的文件,其内容等于either@ 987654336@ 或 V2(但未损坏)

计划的方法

  • 选择一个哈希函数H,将K映射到std::size_t
  • 选择一个整数N > 1
  • 给类C一个互斥体数组tbb::mutex mutex_map[N]
  • void save(K, V) 等待获取对 mutex_map[H(K) % N] 的锁定以执行其文件写入

问题

  • 这是一种明智的做法吗?
  • 您能想出一个比这更有优势的替代方案吗?
  • 是否有一些tbb 数据结构已经封装了互斥映射的这个概念?
    • 想像 std::map<TKey, tbb::mutex> 这样的东西,但界面显示每个可能的键同时具有关联的互斥锁。

【问题讨论】:

  • 如果您不关心两个并发写入,或者一个写入进入而另一个正在进行中,您可能想要使用原子标志而不是互斥锁。

标签: c++ data-structures asynchronous concurrency mutex


【解决方案1】:

是的,这是一种非常明智的做法。我想不出替代方案(除了使用std::mutex 而不是tbb:mutex 的琐碎替代方案。)

您应该选择N 与您认为将同时锁定的互斥锁的数量相比较大。 birthday paradox 表示,如果您希望有 k 个线程同时尝试锁定,那么在您得到 N > o 之前,至少发生一次虚假哈希冲突的概率大于 50% (k2).

我不知道 tbb 数据结构类似于互斥体映射。但是在内部我相信 tbb::malloc 使用了你建议的技巧(线程被随机分配给独立的 malloc 数据结构),并且 tbb::concurrent_hash_map 的实现使得每个都有一个互斥锁哈希桶。

【讨论】:

    【解决方案2】:

    我的后代实现

    #include <vector>
    #include <functional>
    #include <tbb/mutex.h> //could of course use std::mutex instead, if available
    
    template <typename Key, typename Hash = std::hash<Key>>
    class mutex_map
    {
    public:
        typedef Key key_type;
        typedef tbb::mutex value_type;
        static const std::size_t default_bucket_count = 16;
    
    private:
        std::vector<value_type> mutexes;
        Hash hash;
    
    public:
        mutex_map(
            std::size_t bucket_count = default_bucket_count,
            const Hash& hash = Hash())
            : hash(hash)
        {
            mutexes.resize(bucket_count);
        }
    
        std::size_t size() const
        {
            return mutexes.size();
        }
    
        value_type& get(const Key& key)
        {
            auto n = hash(key) % size();
            n += (n < 0) * size();
            return mutexes[n];
        }
    };
    

    【讨论】:

    • std::mutex 不能移动,所以我只使用了一个简单的数组而不是向量。不过感谢您的想法!
    猜你喜欢
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多