列表和多线程环境
Lists and multithreaded environments
我对标准库相当陌生C++并且一直在使用标准库列表进行特定的多线程实现。我注意到使用我在任何教程/博客/论坛帖子中都没有看到的列表可能会有一个技巧,虽然对我来说似乎很明显,但似乎没有人考虑过。所以也许我太新了,可能会错过一些东西,所以希望比我聪明的人可以验证我想要实现的目标或向我解释我做错了什么。
所以我们知道,在一般情况下,标准库容器不是线程安全的 - 但这似乎是一个指导性声明,而不是一个规则。对于列表,似乎对线程安全有一定程度的容忍度。让我解释一下,我们知道如果我们从列表中添加/删除列表,列表不会失效。唯一失效的迭代器是已删除的项 - 您可以使用以下代码行修复它:
it = myList.erase(it)
所以现在假设我们有两个线程,并将它们称为线程 1 和线程 2。
线程 1 的职责是添加到列表中。它将其视为队列,因此它使用 std::list::p ush_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);
}
}
线程 2 在很短的时间内使用锁只是为了知道在哪里停止处理,但在大多数情况下,线程 1 和线程 2 不需要任何其他锁定。此外,如果线程 2 知道当前最后一个元素的范围是灵活的,则它也可以避免锁定。
有人认为我的建议有什么问题吗?
谢谢!
你的程序很活泼。 举一个明显的数据竞赛的例子:std::list
不仅仅是双链接节点的集合。 例如,它还具有一个存储列表中节点数的数据成员(它不需要是单个数据成员,但它必须将计数存储在某个位置)。
两个线程将同时修改此数据成员。 由于这些修改没有同步,因此您的程序是不可靠的。
标准库容器的实例不能在没有外部同步的情况下同时从多个线程进行突变。
- 如何正确取消析构函数中的 Boost deadline_timer(在多线程环境中)?
- 为什么添加延迟会提高此多线程环境中的数据吞吐量?
- Qt::D irectConnection在多线程环境中使用时如何工作?
- 在多线程环境中正确销毁对象
- 多线程环境中C++内存访问
- 为多线程环境包装 c++ new/delete 的安全/好方法
- 在多线程环境中使用 std::call_once() 初始化
- 在多线程环境中交换C 地图对象
- 在多线程环境中使用 libcurl 会导致与 DNS 查找相关的性能非常慢
- 暂停和恢复多线程环境中另一个线程的线程C++技术建议
- 在多线程环境中,什么可能导致"bad file descriptor"?
- 多线程环境中的输出字符串流出现问题
- 信号处理程序在多线程环境中的功能
- 在多线程环境中使用Mysql++的问题
- C++-SQLite3在多线程环境中泄漏句柄
- 如何改进此代码以便在多线程环境下运行
- 在多线程环境中使用atomic保护两个变量
- 多线程环境中的文档锁定
- XSetWMProtocols 和 glXCreateContext 在多线程环境中调用顺序
- 多线程环境 (OpenMP) 中的 OpenCV 会导致分段错误