2

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

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

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

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

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

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

在此先感谢,
ief2

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

4

7 回答 7

7

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

vector.pop_front()并同时vector.push_back()执行会造成各种混乱——假设非标准vector.pop_front()符合其名称所暗示的含义。

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

于 2011-05-04T14:52:27.423 回答
3

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

于 2011-05-04T14:51:32.593 回答
1

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

于 2011-05-04T14:53:37.143 回答
1

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

于 2011-05-04T20:43:57.920 回答
0

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

您可以阅读这个 SO question以查看包装 STL 队列以实现线程安全的示例。

于 2011-05-04T14:56:09.183 回答
0

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

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

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

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

于 2011-05-04T14:57:06.947 回答
0

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

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

于 2011-05-04T15:03:17.780 回答