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

Can c++ mutex cross method/variable? If so, why does it not work here?

本文关键字:如果 不起作用 在这里 为什么 变量 方法 C++      更新时间:2023-10-16

我正在编写一个提供者-消费者程序。有许多消息队列,我想确保每个消息队列中排队的每条消息都有一个顺序递增的索引,例如<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中查找队列的互斥锁,lock(( 它
  • 首先使用 counter_iter-> 作为消息的索引,将 (( 它放在messages
  • 增加指数
  • unlock(( 互斥锁

示例代码如下

/* 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 个锁似乎有点重?

我假设名为messagesunordered_map从空开始(顺便说一句,我是假设正确还是代码没有显示这部分?(,然后在第 8 行:

messages[kname].push_back(make_pair<index, msg>);

我们使用 [] 运算符写入messages,如果密钥尚不存在,则执行插入。

并且不支持同时写入unordered_map(请参阅此问题(,因此需要互斥锁来使这些写入按顺序进行。