Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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++;std条件变量,包含大量共享变量 我正在用C++编写多线程程序,在我的主线程中,我在等待其他线程将包放在不同的队列中。取决于包的种类以及它们来自哪个线程_C++_Multithreading_Variables_Conditional - Fatal编程技术网

C++;std条件变量,包含大量共享变量 我正在用C++编写多线程程序,在我的主线程中,我在等待其他线程将包放在不同的队列中。取决于包的种类以及它们来自哪个线程

C++;std条件变量,包含大量共享变量 我正在用C++编写多线程程序,在我的主线程中,我在等待其他线程将包放在不同的队列中。取决于包的种类以及它们来自哪个线程,c++,multithreading,variables,conditional,C++,Multithreading,Variables,Conditional,队列应该受到互斥锁的保护 但在我看来,我不想做: while(true) if(!queue1->empty) { do stuff } if(!queue2->empty) { do stuff } etc 因此,您需要使用条件变量来向main发出信号,表明某些东西已经改变了。现在我只能阻塞1个条件变量,所以我需要所有这些线程使用相同的条件变量和一个伴随的互斥。现在我不想真的使用这个互斥锁来锁定我所有的线程。这并不意味着当一个线程写入一个队列时,另一个线程不能

队列应该受到互斥锁的保护

但在我看来,我不想做:

while(true)
if(!queue1->empty)
{
     do stuff
}
if(!queue2->empty)
{
     do stuff
}
etc
因此,您需要使用条件变量来向main发出信号,表明某些东西已经改变了。现在我只能阻塞1个条件变量,所以我需要所有这些线程使用相同的条件变量和一个伴随的互斥。现在我不想真的使用这个互斥锁来锁定我所有的线程。这并不意味着当一个线程写入一个队列时,另一个线程不能写入一个完全不同的队列。所以我对每个队列使用单独的互斥体。但是现在我如何使用条件变量附带的这个额外的互斥

如何使用boost实现2个线程和1个队列,与std非常相似。 :

模板
类并发队列
{
私人:
boost::条件变量\u条件变量;
公众:
void wait_for_data()
{
boost::mutex::作用域的_锁锁(_互斥锁);
while(_queue.empty())
{
_条件_变量wait(lock);
}
}
无效推送(数据常量和数据)
{
boost::mutex::作用域的_锁锁(_互斥锁);
bool const was_empty=_queue.empty();
_queue.push(数据);
如果(是空的)
{
_condition_变量。notify_one();
}
}
//照旧休息
};
那么如何解决这个问题呢?

创建一个包含所有工作队列的顶级(可能是循环)队列

这个队列可以由一个互斥锁保护,并且有一个condvar,只有当它从空变为非空时才需要通知它

现在,您的每个队列都可以有自己的互斥体,当它们从空变为非空时,它们只需要触摸共享/顶级队列(及其互斥体)

一些细节将取决于您是希望您的线程只轮流从每个非空队列中获取前面的项目,还是按顺序消费每个队列,但想法是存在的


从非空到非空(但大小增加)也应传递到顶级队列

正如我所说,这取决于你如何消费它们。如果每次队列中都有内容,则执行以下操作:

  • (您已经拥有顶级锁,因此您知道此队列中包含某些内容)
  • 锁定队列
  • 用本地工作副本交换队列内容
  • 从顶级队列中删除该队列
  • 解锁队列
  • 然后,工作队列总是非空的,因此在顶级队列中,或者是空的,因此不在队列中

    如果你不这样做,只是把前面的元素从每个非空队列中拉出来,那么你就有更多的状态要考虑。


    注意,如果

    。。。包裹进来的速度相对较慢。大多数时候,队列都是空的

    您可能只有一个队列,因为没有足够的活动导致大量争用。这大大简化了事情。

    创建一个包含所有工作队列的顶级(可能是循环)队列

    这个队列可以由一个互斥锁保护,并且有一个condvar,只有当它从空变为非空时才需要通知它

    现在,您的每个队列都可以有自己的互斥体,当它们从空变为非空时,它们只需要触摸共享/顶级队列(及其互斥体)

    一些细节将取决于您是希望您的线程只轮流从每个非空队列中获取前面的项目,还是按顺序消费每个队列,但想法是存在的


    从非空到非空(但大小增加)也应传递到顶级队列

    正如我所说,这取决于你如何消费它们。如果每次队列中都有内容,则执行以下操作:

  • (您已经拥有顶级锁,因此您知道此队列中包含某些内容)
  • 锁定队列
  • 用本地工作副本交换队列内容
  • 从顶级队列中删除该队列
  • 解锁队列
  • 然后,工作队列总是非空的,因此在顶级队列中,或者是空的,因此不在队列中

    如果你不这样做,只是把前面的元素从每个非空队列中拉出来,那么你就有更多的状态要考虑。


    注意,如果

    。。。包裹进来的速度相对较慢。大多数时候,队列都是空的


    您可能只有一个队列,因为没有足够的活动导致大量争用。这大大简化了事情。

    我想说,解决问题的关键在于:

    现在我不想真正使用这个互斥锁来锁定所有线程。这并不意味着当一个线程写入一个队列时,另一个线程不能写入一个完全不同的队列。因此,我对每个队列使用单独的互斥锁。

    为什么??因为:

    。。。包裹进来的速度相对较慢。而且队列大部分时间都是空的

    在我看来,你把自己设计成了一个角落,因为你认为你需要一些东西,而实际上你可能不需要它,因为在你提到的使用场景中,一个队列实际上可以工作

    我会说从一个队列开始,看看它能让你走多远。然后,当您遇到一个限制,即您确实有许多线程在一个互斥体上等待时,您将获得有关该问题的更多信息,从而能够更好地解决该问题


    本质上,我想说,您面临这个问题的原因是过早的设计优化,而解决这个问题的方法是立即回溯并更改设计。

    我想说的是解决您问题的关键
    template<typename Data>
    class concurrent_queue
    {
        private:
        boost::condition_variable the_condition_variable;  
        public:
        void wait_for_data()
        {
            boost::mutex::scoped_lock lock(the_mutex);
            while(the_queue.empty())
            {
                 the_condition_variable.wait(lock);
            }
        }
        void push(Data const& data)
        {
             boost::mutex::scoped_lock lock(the_mutex);
             bool const was_empty=the_queue.empty();
             the_queue.push(data);
             if(was_empty)
             {
                 the_condition_variable.notify_one();
             }
         }
         // rest as before
     };
    
    class ParentType {
    public:
      virtual void do_work(...[params]...)=0;
      virtual ~ParentType() {}
    };
    
    class ChildType1 : public ParentType {
    private:
      // all my private variables and functions
    public:
      virtual void do_work(...[params]...) {
        // call private functions and use private variables from ChildType1
      }
    };
    
    class ChildType2: public ParentType {
    private:
      // completely different private variables and functions
    public:
      virtual void do-work(...[params]...) {
        // call private functions and use private variables from ChildType2
      }
    };