c++ - 列表和多线程环境

标签 c++ multithreading list stl

我是 C++ 标准库的新手,一直在使用标准库列表来实现特定的多线程。我注意到使用列表可能有一个技巧,我在任何教程/博客/论坛帖子中都没有看到过,尽管对我来说似乎很明显但似乎没有人考虑过。所以也许我太新了,可能遗漏了一些东西,所以希望比我聪明的人可以验证我正在努力实现的目标或向我解释我做错了什么。

所以我们知道一般的标准库容器不是线程安全的——但这看起来更像是一个指导声明而不是规则。对于列表,似乎对线程安全有一定程度的容忍度。让我解释一下,我们知道如果我们从列表中添加/删除列表不会失效。唯一无效的迭代器是已删除的项目 - 您可以使用以下代码行修复它:

it = myList.erase(it)

现在假设我们有两个线程,称它们为线程 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);
    }
}

线程 2 在很短的时间内使用锁只是为了知道在何处停止处理,但在大多数情况下,线程 1 和线程 2 不需要任何其他锁定。此外,如果线程 2 知道当前最后一个元素的范围是灵活的,那么线程 2 也可以避免锁定。

有人认为我的建议有什么问题吗?

谢谢!

最佳答案

您的程序很活泼。作为一个明显的数据竞争的例子:std::list 不仅仅是双向链接节点的集合。例如,它还有一个数据成员,用于存储列表中的节点数(它不需要是单个数据成员,但必须将计数存储在某处)。

你的两个线程都会同时修改这个数据成员。因为这些修改没有同步,所以您的程序很活泼。

标准库容器的实例不能在没有外部同步的情况下从多个线程同时发生变化。

关于c++ - 列表和多线程环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10964383/

相关文章:

ios - __NSArrayM objectAtIndex 崩溃,但我进行了验证

java - java中从一个套接字线程向所有现有套接字线程广播数据

python - 尝试创建新列表时出现语法错误

c++ - 使用 C++ 在 Linux 上锁定/防止编辑源文件

c++ - 尝试在 C++ 中使用非类型参数专门化模板函数

C线程调度(和asm)

python - 共享引用和平等

python - 按字母顺序排序字符串列表忽略元音python

c++ - 是什么导致 MySQL Connector C++ 程序崩溃?

c++ - 没有空闲存储内存分配的 std::string