1

假设我有一个线程池(例如http://threadpool.sourceforge.net/);我有这个代码:

class Demigod{ 
public:
   Demigod();
   void AskObedienceFast();
   void AskObedienceSlow();
   void WorkHardGodDamn();
   ~Demigod();
private:
   ThreadPool m_PitySlaves;
   int m_Quota;
};
Demigod::Demigod() : m_PitySlaves(manyPlease) { 
}
void Demigod::WorkHardGodDamn(){ 
    //something irelevant just to annoy slaves
}
void Demigod::AskObedienceFast() { 
    for(int q=0; q<m_Quota; ++q){
       m_PitySlaves.schedule(boost::bind(&Demigod::WorkHardGodDamn, this)); 
    }
    m_PitySlaves.wait();
}
void Demigod::AskObedienceSlow() { 
    ThreadPool poorSouls;
    for(int q=0; q<m_Quota; ++q){
       poorSouls.schedule(boost::bind(&Demigod::WorkHardGodDamn, this)); 
    }
    poorSouls.wait();
}
void main(){ 
   Demigod someDude;
   for(size_t i=0; i<dontstop; ++i){ 
      someDude.AskObedienceFast();
   }
}

与 AskObedienceSlow 相比,AskObedienceFast 能否更快、更有效?这样我就可以拥有一些线程(从属)并随时准备工作,而不必在每次调用时浪费时间创建线程池。我知道我可以自己验证代码,但我的问题更广泛,如果这不是从根本上失去其他地方的性能,比如线程池中的那些线程做一些等待过程?它归结为避免昂贵的线程池初始化(和线程)。

4

1 回答 1

2

没有像“等待过程”这样的东西。如果一个线程正在等待(在某个条件下),调度程序只是简单地跳过它,因此这样的线程不会做任何事情,也不会被切换进出。正如您非常正确地指出的那样,线程中最昂贵的任务是设置线程(尽管所有主要操作系统都在采取措施尽可能减少它,以跟上最近的内核倍增),紧随其后的是切换线程上下文。所以你可以看到为什么AskObedienceSlow是可怕的。你的临时建筑应该只是“便宜”的结构,建造和破坏需要尽可能少的时间。ThreadPool绝对不是这样的。甚至AskObedienceFast不会保护您免受上下文切换开销的影响,但这就是为什么更大的线程池并不总是更好的原因,最佳性能大小是根据您的实际工作负载仔细平衡的问题。出于这个原因,一些性能最好的高负载、高吞吐量应用程序是单线程、消息传递设计。用于此类应用程序的编程语言(如 Erlang)是明确的无线程的。

于 2012-11-08T10:33:42.853 回答