多个进程将元素推送到列表STL C++; 我有多个预分叉服务器进程,它们接受请求修改服务器上共享STL C++列表。每个进程只需在列表末尾推送一个新元素并返回迭代器

多个进程将元素推送到列表STL C++; 我有多个预分叉服务器进程,它们接受请求修改服务器上共享STL C++列表。每个进程只需在列表末尾推送一个新元素并返回迭代器,c++,concurrency,stl,multiple-processes,C++,Concurrency,Stl,Multiple Processes,我不确定每个进程应该如何尝试获取列表上的锁?它应该在整个对象上,还是STL列表能够处理并发性,因为我们只是将一个元素推到列表的末尾?标准库容器不提供防止并发修改的自动逻辑保护,因此您需要为队列的每次访问都提供全局锁 您甚至必须小心使用迭代器或对列表元素的引用,因为您可能不一定知道相应的元素何时已从列表中删除。假设您指的是线程而不是进程,您可以共享STL容器,但在同步方面需要小心。STL容器在某种程度上是线程安全的,但您需要了解给定的线程安全保证: 一个容器可以由多个读卡器同时使用 如果一个容器有

我不确定每个进程应该如何尝试获取列表上的锁?它应该在整个对象上,还是STL列表能够处理并发性,因为我们只是将一个元素推到列表的末尾?

标准库容器不提供防止并发修改的自动逻辑保护,因此您需要为队列的每次访问都提供全局锁

您甚至必须小心使用迭代器或对列表元素的引用,因为您可能不一定知道相应的元素何时已从列表中删除。

假设您指的是线程而不是进程,您可以共享STL容器,但在同步方面需要小心。STL容器在某种程度上是线程安全的,但您需要了解给定的线程安全保证:

  • 一个容器可以由多个读卡器同时使用
  • 如果一个容器有一个编写器,则既不能有并发读卡器,也不能有并发编写器
  • 保证是每个容器的,即线程可以同时使用不同的容器,而不需要在它们之间进行同步
  • 这些限制的原因是容器的接口是为了在一个线程内高效使用,并且您不希望妨碍非共享容器的处理,从而可能在多个线程之间共享。此外,容器接口不适用于任何类型的容器维护的并发机制。例如,仅仅因为
    v.empty()
    刚刚返回
    false
    并不意味着
    v.pop()
    可以工作,因为容器现在可以是空的:如果有内部同步,任何锁都会在
    empty()
    返回后释放,并且容器可以在
    pop()之前更改
    被调用


    创建用于不同线程之间通信的队列相对容易。它将使用
    std::mutex
    std::condition\u变量的适当实例化。我认为有一些类似的建议被纳入标准,但它不是标准C++库的一部分。但是,请注意,这样的类不会向插入的元素返回迭代器,因为在您访问它时,元素可能会再次消失,迭代器的用途也会受到质疑。

    在多个进程之间进行这种同步的机制需要开发人员处理几个问题。首先,需要在流程之外设置流程之间共享的内容。这在实践中通常意味着使用
    共享内存

    然后,这些进程需要在访问共享内存方面相互通信。毕竟,如果一个线程开始在共享的数据结构上工作,但在完成操作之前被调出,则会导致数据不一致

    这种同步可以通过linux中的信号量等操作系统结构来完成,并允许相互竞争的进程进行协调

    看 看


    您可以使用
    Boost.Interprocess
    作为参考,它提供了独立于平台的IPC机制实现

    基本上,您需要在列表中使用同步,但为了给出合理的答案,最好看看您编写了什么代码。这听起来可能很愚蠢,但这是一个面试系统设计问题。我想知道我们是否有某种形式的内置并发机制。谢谢你的快速回答。(到目前为止基本上没有代码进展)如果有任何标准库实现了
    std::list
    ,并且能够在多个进程之间共享,我会感到惊讶!但是,通过适当的同步,它们可以与多个线程一起使用。是的,正如迪特玛所说,线程与多进程不同,这就是为什么我需要代码。所以你确定你的意思是
    forked
    “这是一个容器的例子,它受到了Kerrek的进一步保护”回答如果你确实是指多进程,那么你需要研究操作系统中的同步方法。例如,在Linux上,你需要考虑诸如“代码>信号量< /代码>(或者IPC机制)之类的东西。@ DmitryLedentsov:是的,这在一个过程中起作用,但是OP可能需要一些更复杂的共享内存技术……这实际上包含了一些方法,可以在共享内存中创建标准库列表!我相信boost有这样的设备。。。它可能只是我前面提到的那种IPC机制的包装器,但是…@KerrekSB,也许我对
    empty()
    有一个更激进的看法——这样的函数在并发容器中根本没有意义。并发容器没有大小。你所能做的就是尝试检索一个元素,你必须处理在那一点上没有任何元素的可能性。@KerrekSB:我想我们的意见是一致的!我刚才描述了为什么与容器接口进行某种内部同步没有任何意义。仔细想想,很明显,具有内部同步的类只能有一个“fire-and-forget”接口:您向它们抛出一些东西,但不关心任何特定的结果状态,只关心特定的事情发生。A是对“开火并忘记”的更正式的描述。@DietmarKühl。谢谢你的解释。这真的很有帮助。不幸的是,我也想到了这样的事情:。谢谢你的解释。