C ++互斥锁可以跨方法/变量吗?如果是这样,为什么它在这里不起作用?

时间:2018-07-01 15:34:12

标签: c++ multithreading locking mutex

我正在编写一个提供者-消费者程序。消息队列很多,我想确保每个消息队列中排队的每个消息都有一个递增的顺序索引,例如<0, "msga">, <1, "msgb">, ...。顺序保留在每个队列中,并且不同的队列无关。

我使用2个哈希映射和2个互斥锁(我只想使用一个锁,但是失败了。)

(i)第一个哈希映射将队列名称映射到一对<int, mutex *>,其中int表示每个队列的计数器,互斥体在并发请求中保护队列。定义是

using umap_cnt = unordered_map<string, pair<int, mutex* > >;
umap_cnt counters;

(ii)第二个哈希映射将队列名称映射到实际消息<int, MSG>(MSG实际上是字符串),定义为

using umap_msg = unordered_map<string, vector<pair<int, msg> > >;
umap_msg messages`;

我的逻辑是

  • counters中找到队列的互斥体,将其锁定(锁定)
  • 首先使用counter_iter->作为邮件的索引,将其放在messages
  • 增加索引
  • 解锁()互斥锁

示例代码如下

/* File A.cpp */
using umap_msg = unordered_map<string, vector<pair<int, msg> > >;
mutex mtx;
umap_msg messages;
void put(string kname, MSG msg, int index) {
    // If not using mtx here, the message would be out of order.
    // lock_guard<mutex> mtx;
    messages[kname].push_back(make_pair<index, msg>);
}

// Many threads runs producer()
/* File B.cpp*/
using umap_cnt = unordered_map<string, pair<int, mutex* > >
void producer(string kname, MSG msg) {
    umap_cnt::iterator iter = counters.find(kname);
    if (iter == counters.end())
        return;
    // lock the queue
    iter->second.second->lock();
    put(kname, msg, iter->second.first);
    ++iter->second.first; // increase the counter
    iter->second.second->unlock();
}

问题,我发现单个锁不起作用。我必须使用2个互斥锁,一个在生产者中,另一个在投入中,否则我会收到乱序消息或分段错误(不知道为什么)。

我的最初目的是在生产者中仅使用一个锁。每个队列都有其自己的互斥体,并且没有两个线程可以同时获得队列的锁,因此每个队列中的每个消息都应进行排序。但是,结果却出乎我的意料。

为什么第7行需要额外锁定?如果我必须使用2个锁,由于2个锁似乎有点沉重,我是否仍可以优化它?

1 个答案:

答案 0 :(得分:0)

我假设名为unordered_map的{​​{1}}开始为空(顺便说一句,我是否假设是正确的,或者代码未显示此部分?),然后在第8行:

messages

我们使用[] operator写入messages[kname].push_back(make_pair<index, msg>); ,如果密钥不存在,则会执行插入操作。

不支持同时写入messages(请参阅this question),因此需要互斥锁以使这些写入顺序进行。