Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这个型号需要互斥锁吗?_C++_Pthreads_Mutex_Race Condition_Stdvector - Fatal编程技术网

C++ 这个型号需要互斥锁吗?

C++ 这个型号需要互斥锁吗?,c++,pthreads,mutex,race-condition,stdvector,C++,Pthreads,Mutex,Race Condition,Stdvector,我正在设计一个带有服务器的程序,让两个客户端进行通信。一个客户端执行命令,另一个客户端让另一个客户端执行命令 为了实现这一点,我有两个线程:一个线程用于受控客户端,另一个线程用于控制器客户端 受控客户端始终保持连接,有一个包含任务的向量,并在添加任务时执行这些任务。它有一个无限while循环,该循环在连接关闭时停止 控制器客户端将任务添加到向量 现在,由于两个线程之间共享一个向量,可能会出现争用情况,但由于一个线程只添加对象,而另一个线程只弹出对象,这是否必要?我试图用这个问题做一个流程图,但可

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

为了实现这一点,我有两个线程:一个线程用于受控客户端,另一个线程用于控制器客户端

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

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

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

< >我使用C++中的代码> STD::向量< /代码>来实现这一点。 提前感谢,
ief2


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

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

是的,这需要一个互斥锁

vector.pop_-front()
vector.push_-back()
同时执行会造成各种混乱-假设非标准的
vector.pop_-front()
就是这个名字的意思


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

是的,您需要一个互斥对象。在多处理器机器上,两个线程可能同时尝试推送和弹出。一个条件变量来指示什么时候有东西要处理也可能是个好主意。

STL容器不安全。因此,是的,您需要一个锁定机制(即互斥)来确保容器线程安全


您可能会阅读以查看包装STL队列以实现线程安全的示例。

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

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

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


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

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


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

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

感谢您的旁注,非标准的
vector.pop_front()
确实做到了名称所暗示的:)。调用
vector.size()
时是否也应该使用互斥锁?@lef2:Yep,大小是作为结束和开始之间的距离来实现的-在阅读时可能会发生变化。感谢您的澄清!你是说使用队列或列表不需要互斥吗?@Richard Corden:如果我这样做了,它就不会是一个“旁注”,受控客户机实际上是用一个循环实现的,正如你提到的那样。链表实际上是一个极好的主意。我从没想过我自己会用它!非常感谢。我很高兴这对你有用。但要小心,这只适用于您的情况,并且在任何时候,如果有两个线程同时弹出或同时推动。由于数据竞争,列表将被损坏。