互斥锁的正确粒度

时间:2016-12-20 05:14:47

标签: c++ multithreading threadpool

我正在开发一个程序,它从几个搜索文件系统的线程打印正则表达式匹配,每个线程将其id添加到队列,并通知主线程有一些线程要从线程池中删除,这是一个std: :向量。

  

此时,每当我执行时,我都会解锁并锁定互斥锁   对要保护的资源的操作。感觉就像我   想到这一切都是错的,而且我太过细化了。将   最好在进入while循环之前锁定互斥锁,解锁   它弹出队列后,然后再锁定它   !下一次迭代会调用finished_threads.empty()吗?

void RegexSearch::Run()
{
    running = true;
    search_pool.push_back(std::thread([&] { StartPrint(); }));

    /*
    Get directories and create another thread for each subdirectory while there are
    less threads than maximum in the pool.
    */

    fs::path searchDir(directory);

    for (const auto& dir : searchDir)
    {
        if (search_pool.size() >= MAX_THREADS)
        {
            std::unique_lock<std::mutex> lck(mu, std::defer_lock);
            // Wait to be notified that thread is finished execution and another can start.
            max_thread_cond.wait(lck);

            lck.lock();
            while (!finished_threads.empty())
            {
                lck.unlock();

                lck.lock();
                std::thread::id remove_thread = finished_threads.front();
                lck.unlock();

                lck.lock();
                finished_threads.pop();
                lck.unlock();

                std::remove_if(search_pool.begin(), search_pool.end(), [&remove_thread](const std::thread::id &t) { return remove_thread == t; });
                lck.lock();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您必须在!empty()的测试中保持锁定,直到您从队列中删除该项目为止。否则几个线程可能会尝试删除相同的项目 - 也许是最后一个。

我也看到函数开头的push_back没有受到保护。如果可能有多个线程访问search_pool,那么它也必须受到保护。