C++ 与生产者/消费者(排序)和STL的并发性

C++ 与生产者/消费者(排序)和STL的并发性,c++,stl,concurrency,C++,Stl,Concurrency,我有以下情况:我有两个线程 thread1,它是一个工作线程,执行算法直到其输入列表大小>0 thread2,它是异步的(用户驱动的),可以将元素添加到要处理的输入列表中 现在,thread1循环执行与以下类似的操作 list input_list list buffer_list if (input_list.size() == 0) sleep while (input_list.size() > 0) { for (item in input_list) {

我有以下情况:我有两个线程

  • thread1,它是一个工作线程,执行算法直到其输入列表大小>0
  • thread2,它是异步的(用户驱动的),可以将元素添加到要处理的输入列表中
现在,thread1循环执行与以下类似的操作

list input_list
list buffer_list

if (input_list.size() == 0)
  sleep

while (input_list.size() > 0) {
  for (item in input_list) {
    process(item);
    possibly add items to buffer_list
  }
  input_list = buffer_list (or copy it)
  buffer_list = new list (or empty it)
  sleep X ms (100 < X < 500, still have to decide)
}
列表输入\u列表
列表缓冲区列表
如果(输入_list.size()==0)
睡觉
while(input_list.size()>0){
用于(输入列表中的项目){
过程(项目);
可能会将项目添加到缓冲区列表中
}
输入\列表=缓冲\列表(或复制)
缓冲区列表=新列表(或清空)
睡眠X毫秒(100
现在,thread2只需将元素添加到buffer_列表(这将是算法的下一步),如果thread1被停止,它可能会唤醒thread1

我试图理解在这种情况下会发生多线程问题,假设我用STL帮助它编程到C++(没有关于线程安全性的假设),当然我也可以访问标准库(比如互斥)。 我希望避免thread2可能出现的任何延迟,因为它绑定到用户界面,并且会造成延迟。我曾考虑使用3个列表来避免同步问题,但到目前为止我还不确定。根据这一具体情况,我仍然不确定STL中是否有更安全的容器。。我不想把互斥锁放在所有东西之外,从而损失太多的性能

如果您有任何建议,我们将不胜感激,谢谢

编辑: 这就是我目前所做的,我想知道它是否线程安全且足够高效:

std::set<Item> *extBuffer, *innBuffer, *actBuffer;

void thread1Function()
{
  actBuffer->clear();
  sem_wait(&mutex);
  if (!extBuffer->empty())
    std::swap(actBuffer, extBuffer);
  sem_post(&mutex);
  if (!innBuffer->empty())
  {
    if (actBuffer->empty())
      std::swap(innBuffer, actBuffer);
    else if (!innBuffer->empty())
      actBuffer->insert(innBuffer->begin(), innBuffer->end());
  }

  if (!actBuffer->empty())
  {
    set<Item>::iterator it;
    for (it = actBuffer.begin; it != actBuffer.end(); ++it)
      // process
      // possibly innBuffer->insert(...)
  }
}

void thread2Add(Item item)
{
  sem_wait(&mutex);
  extBuffer->insert(item);
  sem_post(&mutex);

}
std::set*extBuffer、*innBuffer、*actBuffer;
void thread1Function()
{
actBuffer->clear();
sem_等待(&mutex);
如果(!extBuffer->empty())
交换(actBuffer,extBuffer);
sem_post(和互斥);
如果(!innBuffer->empty())
{
如果(actBuffer->empty())
交换(innBuffer,actBuffer);
如果(!innBuffer->empty()),则为else
actBuffer->insert(innBuffer->begin(),innBuffer->end());
}
如果(!actBuffer->empty())
{
set::迭代器;
for(it=actBuffer.begin;it!=actBuffer.end();+it)
//过程
//可能在缓冲区->插入(…)
}
}
无效螺纹2添加(项目)
{
sem_等待(&mutex);
extBuffer->insert(项目);
sem_post(和互斥);
}

也许我应该打开另一个问题

您只需要在插入、删除或访问容器大小时使用互斥锁。您可以开发一个类来封装容器,该类将具有互斥锁。这将使事情保持简单,并且类将处理使用互斥的功能。如果您限制项的访问(函数/接口的公开内容)并使函数变小(仅调用容器类函数enacapsulated in the mutex),它们将相对较快地返回。在这种情况下,您应该只需要在列表中列出

根据系统的不同,如果您有可用的信号量,您可能希望检查它们是否更有效,并使用它们而不是互斥。同样的概念也适用,只是方式不同而已


您可能需要检查保护的概念,以防其中一个线程死亡,您不会遇到死锁情况。

如果您担心thread2会因为thread1持有锁而被阻塞很长时间,那么请确保thread1保护只在很短的时间内持有锁

如果您有两个缓冲区列表实例,这可以很容易地实现。所以你的尝试已经在正确的方向上了

每个缓冲区都用指针指向。一个指针用于将项目插入列表(thread2),另一个指针用于处理其他列表(thread1)中的项目。螺纹2的插入操作必须由锁包围

如果thread1处理完所有项,它只需交换指针(例如,使用std::swap),这是一个非常快速的操作,必须由锁包围。不过,只有交换操作。项目的实际处理是无锁的

此解决方案具有以下优点:

  • thread1中的锁定时间总是很短,因此它阻止thread2的时间非常短
  • 没有固定的缓冲区动态分配,这更快,也不太可能导致内存泄漏错误

  • 你们有什么“标准图书馆”?C++11,boost.thread,pthreads?我实际上是在iOS上开发的,所以我想这只是你提到的pthreads的一个很好的例子:看,这确实是我试图实现的,问题是thread1可以在工作时向
    缓冲区列表添加元素,这就是为什么我考虑使用2个缓冲区列表,这样当thread1要交换时,它会将锁带到
    buffer\u list 2
    ,将其元素添加到
    buffer\u list
    ,然后有效地交换它们。