这个模型需要互斥体吗?
我正在设计一个带有服务器的程序,让两个客户端进行通信。有一个客户端执行命令,另一个客户端让另一个客户端执行命令。
为了完成这项工作,我有两个线程:一个线程用于受控客户端,另一个线程用于控制器客户端。
受控客户端始终保持连接,具有包含任务的向量,并在添加任务时执行这些任务。它有一个无限的 while 循环,当连接关闭时该循环停止。
控制器-客户端将任务添加到向量中。
现在,由于两个线程之间共享一个向量,因此可能会发生竞争条件,但由于一个线程仅添加对象,而另一个线程仅弹出对象,因此有必要吗?我试图制作一个流程图来解决这个问题,但也许还不清楚。我真的不知道如何创建流程图:
我正在使用 C++ 中的 std::vector
意识到这一点。
预先感谢,
ief2
编辑:附加问题:vector.size()
调用是否需要互斥锁?
I'm designing a program with a server that let's two clients communicate. There's one client that executes commands and another that makes the other client execute them.
To make this work, I have two threads: one thread for the controlled-client, another for the controller-client.
The controlled-client always stays connected, has a vector with tasks and executes these tasks if a task is added. It has an infinite while loop which is stopped when the connection is closed.
The controller-client adds tasks to the vector.
Now since there is an vector shared between two threads a race condition may occur, but since one thread only adds objects and the other only pops objects, is that necessary? I tried to make a flowchart with this problem, but maybe it isn't clear. I don't really know how to create a flowchart:
I'm using std::vector <CustomClass>
from C++ to realize this.
Thanks in advance,
ief2
EDIT: Additional Question: Does the vector.size()
call need a mutex?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的,这需要一个互斥体。
vector.pop_front()
和vector.push_back()
同时执行会造成各种混乱 - 假设非标准vector.pop_front()
code> 的作用正如其名称所暗示的那样。旁注:使用队列或列表而不是向量
Yes, this needs a mutex.
vector.pop_front()
andvector.push_back()
executing at the same time would create all sorts of mess - assuming the nonstandardvector.pop_front()
does what the name implies.Side note: use a queue or a list rather than a vector
您应该控制对向量的访问。您不想尝试同时推送和弹出。
You should control access to the vector. You don't want to be trying to push and pop simultaneously.
是的,你需要一个互斥体。在多处理器计算机上,两个线程可能会同时尝试推送和弹出。使用条件变量来指示何时需要处理某些内容可能也是一个好主意。
Yes you need a mutex. On a multiple processor machine both threads could be trying to push and pop at the same time. A condition variable to indicate when there is something to process might be a good idea too.
我想知道受控客户端是如何实现的。是不是一个循环不断的检查任务队列?如果是这样,并且您认为效率更重要,您可以将任务队列实现为单链表,并且仍然具有线程安全和无锁的实现。您所需要的只是列表中的一个哑节点,并且头指向这个哑节点。空列表表示哑节点的下一个字段为空。当你弹出时,你只需将头从当前的哑节点移动到下一个节点,该节点将成为新的哑节点。当您推送时,您只需追加任务,因为列表不为空(至少包含一个哑节点)。这只适用于双线程场景。
I'm wondering how the controlled-client is implemented. Is it a loop that keeps checking the task queue? If it is the case and you believe that efficiency is more important, you can implement the task queue as a singly-linked list and still have a thread-safe and lock-free implementation. All you need is a dumb node in the list and the head is pointed to this dumb node. The empty list is represented as the dumb node's next field is null. When you pop, you just move the head from the current dumb node to the next node which becomes the new dumb node. When you push, you just append the task, since the list is not empty(contains at least a dumb node). This only works for two-thread scenario.
STL 容器不是线程安全的。所以,是的,您需要一个锁定机制(即互斥体)来使容器线程安全。
您可以阅读这个SO问题来查看包装STL队列的示例线程安全。
STL containers are not thred-safe. So yes you need a locking mechanism (i.e a mutex) to make the container thread-safe.
You may read this SO question to see an example for wrapping an STL queue for thread-safety.
流程图通常不是一个好主意。
需要同步。在多个线程中从
std::vector
插入或删除是不安全的。如果一个线程同时推送而另一个线程弹出,但推送导致向量的内部数组被重新分配,会发生什么情况?弹出线程正在访问一些可能不再使用的内存。
如果一个线程正在读取而另一个线程正在推送,则可能会发生类似的情况。如果推送导致向量重新分配,则读取现在访问的内存很可能不再有效。
Flow charts usually aren't a good idea.
Synchronization is required. Inserting or erasing from an
std::vector
in multiple threads is not safe.What happens if you one thread pushes and the other thread pops at the same time, but the push causes the vector's internal array to be reallocated? The popping thread is accessing some memory that's possibly no longer in use.
A similar situation can occur if one thread is reading and the other thread is pushing. If the push causes the vector to reallocate, the read is now accessing memory that's most likely no longer valid.
不,您不需要互斥锁,但某种同步是必要的。我建议不要使用无限定时循环,而是使用事件。如果生产者已完成对共享集合的写入,则让其发出信号;当消费者完成读取命令时,让其发出信号(在阻止生产者写入时不要开始执行命令)。
这会停止检查空向量中命令的无用 CPU 周期。
No you don't need a mutex, but some kind of synchronisation is necessary. I would recommend not using infinite timed loops, and would use events instead. Have the producer signal if it has finished writing to the shared collection, and have the consumer signal when it is finished reading the commands (don't start executing the commands while preventing the producer from writing).
This stop useless CPU cycles of checking for commands in an empty vector.