【问题标题】:Does this model need a mutex?这个模型需要互斥体吗?
【发布时间】:2011-05-04 14:49:26
【问题描述】:

我正在设计一个带有服务器的程序,让两个客户端进行通信。一个客户端执行命令,另一个客户端执行命令。

为了完成这项工作,我有两个线程:一个线程用于受控客户端,另一个用于控制器客户端。

受控客户端始终保持连接,有一个带有任务的向量,如果添加了任务,则执行这些任务。它有一个无限循环,当连接关闭时停止。

控制器-客户端将任务添加到向量中。

现在由于两个线程之间共享一个向量,可能会出现竞争条件,但是由于一个线程只添加对象而另一个只弹出对象,这有必要吗?我试图为这个问题制作一个流程图,但可能不清楚。我真的不知道如何创建流程图:

我正在使用 C++ 中的 std::vector <CustomClass> 来实现这一点。

提前致谢,
ief2

编辑:附加问题:vector.size() 调用是否需要互斥锁?

【问题讨论】:

    标签: c++ pthreads mutex race-condition stdvector


    【解决方案1】:

    是的,这需要一个互斥体。

    vector.pop_front()vector.push_back() 同时执行会造成各种混乱 - 假设非标准的 vector.pop_front() 顾名思义。

    旁注:使用队列或列表而不是向量

    【讨论】:

    • 感谢旁注,非标准的vector.pop_front() 确实做到了顾名思义:)。调用 vector.size() 时我是否也应该使用互斥锁?
    • @lef2: 是的,大小是作为 end 和 begin 之间的距离实现的——在你阅读它们时可能会改变。
    • 感谢您的澄清!
    • 你是说使用队列或列表不需要需要互斥体吗?
    • @Richard Corden:如果我这样做了,那将不是“旁注”
    【解决方案2】:

    您应该控制对向量的访问。您不想同时尝试推送和弹出。

    【讨论】:

      【解决方案3】:

      是的,您需要一个互斥锁。在多处理器机器上,两个线程可能同时尝试推送和弹出。用于指示何时需要处理的条件变量可能也是一个好主意。

      【讨论】:

        【解决方案4】:

        我想知道受控客户端是如何实现的。它是一个不断检查任务队列的循环吗?如果是这样,并且您认为效率更重要,您可以将任务队列实现为单链表,并且仍然具有线程安全和无锁的实现。您所需要的只是列表中的一个哑节点,并且头部指向这个哑节点。空列表表示为哑节点的下一个字段为空。当你弹出时,你只需将头部从当前的哑节点移动到下一个成为新哑节点的节点。当您推送时,您只需附加任务,因为列表不为空(至少包含一个哑节点)。这仅适用于双线程场景。

        【讨论】:

        • 受控客户端确实是用你提到的循环实现的。链表实际上是一个绝妙的主意。我从没想过我会自己使用它!谢谢!
        • 我很高兴这对你有用。但请注意,这仅适用于您的情况,并且在任何时候,如果有两个线程同时弹出或同时推送。由于数据竞争,该列表将被损坏。
        【解决方案5】:

        STL 容器不是线程安全的。所以是的,你需要一个锁定机制(即互斥锁)来使容器线程安全。

        您可以阅读this SO question 以查看包装 STL 队列以确保线程安全的示例。

        【讨论】:

          【解决方案6】:

          流程图通常不是一个好主意。

          需要同步。在多个线程中插入或删除 std::vector 是不安全的。

          如果您一个线程推送而另一个线程同时弹出,但推送导致向量的内部数组被重新分配,会发生什么?弹出线程正在访问一些可能不再使用的内存。

          如果一个线程正在读取而另一个线程正在推送,则可能会发生类似的情况。如果推送导致向量重新分配,则读取现在正在访问很可能不再有效的内存。

          【讨论】:

            【解决方案7】:

            不,您不需要互斥锁,但需要某种同步。我建议不要使用无限定时循环,而是使用事件。如果生产者已经完成对共享集合的写入,则发出信号,并在完成读取命令时发出消费者信号(不要在阻止生产者写入的同时开始执行命令)。

            这会停止检查空向量中的命令的无用 CPU 周期。

            【讨论】:

              猜你喜欢
              • 2011-01-20
              • 1970-01-01
              • 2015-07-19
              • 2015-10-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-23
              相关资源
              最近更新 更多