nnd*_*wan 3 c++ multithreading stl list
我是C++标准库的新手,并且一直在使用标准库列表来实现特定的多线程实现.我注意到使用我在任何教程/博客/论坛帖子上都没有看过的列表可能会有一些技巧,虽然对我来说似乎显而易见,似乎没有人考虑过.所以也许我太新了,可能会遗漏一些东西,所以希望比我聪明的人可以验证我想要实现的目标,或者向我解释我做错了什么.
因此我们知道,通常标准库容器不是线程安全的 - 但这似乎是一个指导性声明而不是规则.使用列表似乎对线程安全有一定程度的容忍度.让我解释一下,我们知道如果我们从列表中添加/删除列表不会失效.获取无效的唯一迭代器是已删除的项 - 您可以使用以下代码行修复它:
it = myList.erase(it)
Run Code Online (Sandbox Code Playgroud)
所以现在让我们说我们有两个线程并将它们称为线程1和线程2.
线程1的职责是添加到列表中.它将其视为队列,因此它使用std :: list :: push_back()函数调用.
线程2的职责是将存储在列表中的数据作为队列进行处理,然后在处理之后将从列表中删除元素.
它保证线程2不会删除列表中刚刚在其处理过程中添加的元素,并且线程1保证它将提前排队必要的数据以进行线程2的处理.但是,请记住,在线程2的处理过程中可以添加元素.
因此,似乎这是在这个多线程环境中合理使用列表而不使用锁来进行数据保护.我说它合理的原因是因为,本质上,线程2将只处理数据到现在为止它可以检索由以下伪代码显示的当前结束迭代器:
Thread 2 {
iter = myList.begin();
lock();
iterEnd = myList.end(); // lock data temporarily in order to get the current
// last element in the list
unlock();
// perform necessary processing
while (iter != iterEnd) {
// process data
// ...
// remove element
iter = myList.erase(iter);
}
}
Run Code Online (Sandbox Code Playgroud)
线程2使用锁定的时间非常短,只是为了知道停止处理的位置,但大多数情况下,线程1和线程2不需要任何其他锁定.此外,如果线程2知道当前最后一个元素的范围是灵活的,那么线程2也可以避免锁定.
有人看到我的建议有什么问题吗?
谢谢!
你的节目很活泼.作为一个明显的数据竞争的例子: std::list不仅仅是双链节点的集合.例如,它还有一个数据成员,用于存储列表中的节点数(它不需要是单个数据成员,但必须在某处存储计数).
您的两个线程将同时修改此数据成员.因为这些修改没有同步,所以你的程序很活泼.
没有外部同步,标准库容器的实例不能同时从多个线程变异.