How to limit the number of running instances in C++(C++中如何限制运行实例的数量)
问题描述
我有一个分配大量内存的 C++ 类.它通过调用第三方库来实现这一点,该库旨在在无法分配内存时崩溃,有时我的应用程序会在并行线程中创建我的类的多个实例.由于线程太多,我崩溃了.我对解决方案的最佳想法是确保永远不会有超过三个实例同时运行.(这是一个好主意吗?)我目前实现 that 的最佳想法是使用 boost 互斥锁.类似于以下伪代码的内容,
I have a c++ class that allocates a lot of memory. It does this by calling a third-party library that is designed to crash if it cannot allocate the memory, and sometimes my application creates several instances of my class in parallel threads. With too many threads I have a crash. My best idea for a solution is to make sure that there are never, say, more than three instances running at the same time. (Is this a good idea?) And my current best idea for implementing that is to use a boost mutex. Something along the lines of the following pseudo-code,
MyClass::MyClass(){
  my_thread_number = -1; //this is a class variable
  while (my_thread_number == -1)
    for (int i=0; i < MAX_PROCESSES; i++)
      if(try_lock a mutex named i){
        my_thread_number = i;
        break;
      }
  //Now I know that my thread has mutex number i and it is allowed to run
}
MyClass::~MyClass(){
    release mutex named my_thread_number
}
如您所见,我不太确定此处互斥锁的确切语法.总而言之,我的问题是
As you see, I am not quite sure of the exact syntax for mutexes here.. So summing up, my questions are
- 当我想通过限制线程数来解决内存错误时,我是否在正确的轨道上?
 - 如果是,我应该使用互斥锁还是其他方式?
 - 如果是,我的算法是否合理?
 - 是否有一个很好的例子来说明如何将 try_lock 与 boost 互斥锁一起使用?
 
<小时>
我意识到我在谈论线程,而不是进程.我参与构建一个可以在 linux 和 Windows 上运行的应用程序...
I realized I am talking about threads, not processes. I am involved in building an application that can run on both linux and Windows...
推荐答案
这是实现您自己的信号量"的一种简单方法(因为我认为标准库或 boost 没有).这选择了一种合作"的方法,工人会互相等待:
Here's a simplistic way to implement your own 'semaphore' (since I don't think the standard library or boost have one). This chooses a 'cooperative' approach and workers will wait for each other:
#include <boost/thread.hpp>
#include <boost/phoenix.hpp>
using namespace boost;
using namespace boost::phoenix::arg_names;
void the_work(int id)
{
    static int running = 0;
    std::cout << "worker " << id << " entered (" << running << " running)
";
    static mutex mx;
    static condition_variable cv;
    // synchronize here, waiting until we can begin work
    {
        unique_lock<mutex> lk(mx);
        cv.wait(lk, phoenix::cref(running) < 3);
        running += 1;
    }
    std::cout << "worker " << id << " start work
";
    this_thread::sleep_for(chrono::seconds(2));
    std::cout << "worker " << id << " done
";
    // signal one other worker, if waiting
    {
        lock_guard<mutex> lk(mx);
        running -= 1;
        cv.notify_one(); 
    }
}
int main()
{
    thread_group pool;
    for (int i = 0; i < 10; ++i)
        pool.create_thread(bind(the_work, i));
    pool.join_all();
}
现在,我认为最好有一个由 n 个工人组成的专用池轮流从队列中取出他们的工作:
Now, I'd say it's probably better to have a dedicated pool of n workers taking their work from a queue in turns:
#include <boost/thread.hpp>
#include <boost/phoenix.hpp>
#include <boost/optional.hpp>
using namespace boost;
using namespace boost::phoenix::arg_names;
class thread_pool
{
  private:
      mutex mx;
      condition_variable cv;
      typedef function<void()> job_t;
      std::deque<job_t> _queue;
      thread_group pool;
      boost::atomic_bool shutdown;
      static void worker_thread(thread_pool& q)
      {
          while (auto job = q.dequeue())
              (*job)();
      }
  public:
      thread_pool() : shutdown(false) {
          for (unsigned i = 0; i < boost::thread::hardware_concurrency(); ++i)
              pool.create_thread(bind(worker_thread, ref(*this)));
      }
      void enqueue(job_t job) 
      {
          lock_guard<mutex> lk(mx);
          _queue.push_back(std::move(job));
          cv.notify_one();
      }
      optional<job_t> dequeue() 
      {
          unique_lock<mutex> lk(mx);
          namespace phx = boost::phoenix;
          cv.wait(lk, phx::ref(shutdown) || !phx::empty(phx::ref(_queue)));
          if (_queue.empty())
              return none;
          auto job = std::move(_queue.front());
          _queue.pop_front();
          return std::move(job);
      }
      ~thread_pool()
      {
          shutdown = true;
          {
              lock_guard<mutex> lk(mx);
              cv.notify_all();
          }
          pool.join_all();
      }
};
void the_work(int id)
{
    std::cout << "worker " << id << " entered
";
    // no more synchronization; the pool size determines max concurrency
    std::cout << "worker " << id << " start work
";
    this_thread::sleep_for(chrono::seconds(2));
    std::cout << "worker " << id << " done
";
}
int main()
{
    thread_pool pool; // uses 1 thread per core
    for (int i = 0; i < 10; ++i)
        pool.enqueue(bind(the_work, i));
}
附注.如果您愿意,您可以在那里使用 C++11 lambdas 而不是 boost::phoenix.
PS. You can use C++11 lambdas instead boost::phoenix there if you prefer.
这篇关于C++中如何限制运行实例的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++中如何限制运行实例的数量
				
        
 
            
        - 近似搜索的工作原理 2021-01-01
 - 如何对自定义类的向量使用std::find()? 2022-11-07
 - Stroustrup 的 Simple_window.h 2022-01-01
 - 与 int by int 相比,为什么执行 float by float 矩阵乘法更快? 2021-01-01
 - 静态初始化顺序失败 2022-01-01
 - STL 中有 dereference_iterator 吗? 2022-01-01
 - 从python回调到c++的选项 2022-11-16
 - 使用/clr 时出现 LNK2022 错误 2022-01-01
 - C++ 协变模板 2021-01-01
 - 一起使用 MPI 和 OpenCV 时出现分段错误 2022-01-01
 
						
						
						
						
						
				
				
				
				