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

  • 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)
    }
    

    现在 thread2 将只向 buffer_list 添加元素(这将是算法的下一次传递),并且如果线程 1 停止,则可能设法唤醒它。

    我试图了解在这种情况下会发生哪些多线程问题,假设我在 STL 的帮助下将其编程为 C++(不假设实现的线程安全),并且我当然可以访问标准库(像互斥锁)。

    我想避免使用 thread2 出现任何可能的延迟,因为它绑定(bind)到用户界面并且会造成延迟。我正在考虑使用 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);
    
    }
    

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

    最佳答案

    如果您担心由于线程 1 持有锁而导致线程 2 被长时间阻塞,那么请确保线程 1 保证只占用锁很短的时间。

    如果您有两个缓冲区列表实例,这很容易实现。所以你的尝试已经朝着正确的方向发展。

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

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

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

  • thread1 中的锁总是很短,所以它可能阻塞 thread2 的时间是最小的
  • 没有恒定的动态分配缓冲区,这样速度更快,并且不太可能导致内存泄漏错误。
  • 关于c++ - 与生产者/消费者(某种)和 STL 的并发,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9732939/

    10-15 00:29