多少互斥和cond变量
How many mutex and cond variable?
我在pthread池上工作,将有五个独立的线程和一个队列。所有五个线程都在竞争从队列中获得一个作业,我知道我需要执行锁定/解锁和等待/信号的基本想法。
但我不确定我应该有多少互斥和cond变量。现在我只有一个互斥锁和cond变量,所有五个线程都会使用它
一个互斥对象和至少一个条件变量。
一个互斥对象,因为有一个"东西"(即内存)需要同步访问:所有工作线程和推动工作的线程之间的共享状态。
一个或多个线程需要等待的每个条件都有一个条件变量。至少你需要一个用于等待新作业的条件变量,这里的条件是:"还有更多的事情要做吗?"(或者反过来:"工作队列是空的吗?")。
一个更实质性的答案是,互斥体和相关的条件变量之间存在一对多的关系,共享状态和互斥体之间也存在一对一的关系。根据您告诉我们的内容以及您正在学习的内容,我建议您的设计只使用一种共享状态。当你需要更多的状态时,我建议你寻找一些更高级别的概念(例如渠道、未来/承诺)来建立在抽象之上。
在任何情况下,都不要将同一个条件变量与不同的互斥对象一起使用。
详细介绍@Ivan的解决方案。。。
您可以使用计数信号量+原子操作来创建一个非常高效的队列,而不是互斥+条件变量。
semaphore dequeue_sem = 0;
semaphore enqueue_sem = 37; // or however large you want to bound your queue
排队操作只是:
wait_for(enqueue_sem)
atomic_add_to_queue(element)
signal(dequeue_sem)
排队操作为:
wait_for(dequeue_sem)
element = atomic_remove_from_queue()
signal(enqueue_sem)
"atomic_add_to_queue"answers"atomic_remove_from_queue"通常使用atomiccompare&在一个紧密的循环中交换。
除了对称性之外,这个公式还限制了队列的最大大小;如果线程在一个完整的队列上调用enqueue(),它就会阻塞。对于多线程环境中的任何队列,这几乎可以肯定是您想要的。(您的计算机内存有限;应尽可能避免无限制地使用它。)
如果你坚持使用互斥锁和条件变量,你需要两个条件,一个用于入队等待(和deque发出信号),另一个用于相反的方式。条件分别表示"队列未满"answers"队列未空",入队/出队代码也同样对称。
我认为,如果您将队列组织为堆栈/链表,您可以从队列中窃取工作,而不需要通过互锁操作进行锁定(它需要信号量而不是条件变量,以防止在对此答案的注释中描述的问题)。
伪代码是这样的:
- 候选者=头部
- if(candidate==null)wait_for_symaphore
- if(candidate==InterlockedCompareExchange(head,candidate->next,候选者))perform_work(candidate->data)
- 否则转到1
当然,在这种情况下,向队列中添加工作也应该通过InterlockedCompareExchange并发出信号量。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- 将包含C样式数组的对象初始化为成员变量(C++)
- 当vector是tje全局变量时,c++中vector的内存管理
- 通过多个头文件使用常量变量
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 执行函数时导致崩溃的变量
- 多少互斥和cond变量