我正在编写一个提供者-消费者程序。消息队列很多,我想确保每个消息队列中排队的每个消息都有一个递增的顺序索引,例如<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
中找到队列的互斥体,将其锁定(锁定)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个锁似乎有点沉重,我是否仍可以优化它?
答案 0 :(得分:0)
我假设名为unordered_map
的{{1}}开始为空(顺便说一句,我是否假设是正确的,或者代码未显示此部分?),然后在第8行:
messages
我们使用[] operator写入messages[kname].push_back(make_pair<index, msg>);
,如果密钥不存在,则会执行插入操作。
不支持同时写入messages
(请参阅this question),因此需要互斥锁以使这些写入顺序进行。