安全的多线程计数器增量

Ale*_*exS 1 c++ algorithm multithreading boost boost-thread

例如,我有一些由多个线程同时计算的工作.

出于演示目的,工作在while循环内执行.在单次迭代中,每个线程执行其自己的工作部分,在下一次迭代开始之前,计数器应该递增一次.

我的问题是每个线程都会更新计数器.

由于这似乎是一件相对简单的事情,我认为有一种"最佳实践"或常用方法可以解决这个问题?

下面是一些示例代码来说明问题并帮助讨论.(我使用提升线程)

class someTask {
public:
    int mCounter; //initialized to 0
    int mTotal; //initialized to i.e. 100000
    boost::mutex cntmutex;                
    int getCount()
    {
            boost::mutex::scoped_lock lock( cntmutex );
            return mCount;
    }
    void process( int thread_id, int numThreads )
    {
        while ( getCount() < mTotal )
        {
            // The main task is performed here and is divided 
            // into sub-tasks based on the thread_id and numThreads

                            // Wait for all thread to get to this point

            cntmutex.lock();
            mCounter++;  // < ---- how to ensure this is only updated once?
            cntmutex.unlock();
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 5

我在这里看到的主要问题是你的理由太低了.因此,我将提出一个基于新的C++ 11线程API的替代解决方案.

主要的想法是你基本上有一个时间表 - > dispatch - > do - > collect - >循环例程.在你的例子中,你试图在do阶段内对所有这些进行推理是非常困难的.使用相反的方法可以更容易地表达您的模式.

首先,我们将要完成的工作隔离在自己的例行程序中:

void process_thread(size_t id, size_t numThreads) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

现在,我们可以轻松调用此例程:

#include <future>
#include <thread>
#include <vector>

void process(size_t const total, size_t const numThreads) {
    for (size_t count = 0; count != total; ++count) {
         std::vector< std::future<void> > results;

         // Create all threads, launch the work!
         for (size_t id = 0; id != numThreads; ++id) {
             results.push_back(std::async(process_thread, id, numThreads));
         }

         // The destruction of `std::future`
         // requires waiting for the task to complete (*)
    }
}
Run Code Online (Sandbox Code Playgroud)

(*)看到这个问题.

你可以std::async 在这里阅读更多,这里提供一个简短的介绍(它们似乎与发布政策的效果有些矛盾,哦).这里更简单的是让实现决定是否创建OS线程:它可以根据可用内核的数量进行调整.

请注意如何通过删除共享状态来简化代码.因为线程没有共享,我们不再需要明确地担心同步!