0

我正在使用 a map<int, queue<string>>,其中int是指消息的来源,而 是queue保存消息。一个线程将消息推入队列,另一个线程将它们推出队列。

这是一个客户端-服务器程序——当客户端发送消息时,消息被推入队列。

我目前正在使用(伪代码)

/*receive message in thread 1*/
map<int, queue<string>> test_map; 
int client_id = 2;
string msg = received_from_client(client_id);
testmap[client_id].push(msg);

/*process message in thread 2*/
string msg_to_process testmap[client_id].front();
test_map[client_id].pop();

if (testmap[client_id].empty())
{
    testmap.erase(client_id);
}

我从这个问题中知道,不同之处在于插入不会覆盖现有的密钥——当我将东西推入队列时这是否适用?使用插入是否更安全,或者我正在做的事情是否[]足够?

另外 - 虽然系统在任何时候都应该只有一条消息在队列中,但我正在通过使用map<int, queue>而不是使用map<int,string>.

编辑:我也有一个关于多线程的问题 - 当线程 1 尝试插入映射而线程 2 删除键时会发生什么,因为队列是空的(在它处理完消息之后)。这是对此的定量回答,是否使用[]insert()帮助使其不再是线程安全的?

4

1 回答 1

0

队列没有键或 [] 运算符,因此无法真正回答您的第一个问题。您通过推到后面插入队列。如果那里有元素,它将追随它们。如果有的话,您可以通过从前面弹出东西来读取队列。除此之外,您不会在任何地方阅读或写作。

至于地图,就像你说的,如果它不存在,插入将添加一个新的键值对。它不会覆盖现有的密钥。Find 将找到一个值,如果它已经存在,但如果它不存在则不会插入它。然后 [] 运算符同时执行这两项操作,还允许您更改现有元素。这里的文档非常好。

需要注意的一件事是,使用地图的 [] 运算符从地图中读取也会使用该键将默认值类型元素插入到地图中,这可能不是您第一次看到它时所期望的。

std::map<int, int> myMap;
if(myMap[1] == 0) //[] create's a key-value pair <1,0>
   cout << "This will output";
if(myMap.size() == 1)
   cout << "This too";

至于线程安全方面,没有任何 STL 容器是基于标准的线程安全的。您需要在代码中添加适当的锁定,以防止您所询问的内容。如果 2 个线程同时尝试从队列中读取和写入,几乎肯定会导致错误。我会在谷歌上搜索关于编写线程安全程序的一般帮助,以了解如何做到这一点。

于 2013-04-19T06:53:27.970 回答