【问题标题】:Proper Granularity for Mutex Lock互斥锁的适当粒度
【发布时间】:2016-12-20 05:14:47
【问题描述】:

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

此时,每当我执行时,我都会解锁和锁定互斥锁 对要保护的资源的操作。感觉就像我在 想到这一切都错了,而且我太细化了。将 最好在进入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();
            }
        }
    }
}

【问题讨论】:

    标签: c++ multithreading threadpool


    【解决方案1】:

    在您从队列中删除该项目之前,您当然必须保持对!empty() 的测试的锁定。否则,多个线程可能会尝试删除同一个项目 - 可能是最后一个。

    我还看到函数开头的push_back 是不受保护的。如果可能有多个线程访问search_pool,也必须对其进行保护。

    【讨论】:

    • 哦,这很有道理。在调用 Run() 之前没有线程访问 thread_pool。是否仍然需要使用互斥锁来锁定它?
    • 标准容器不是线程安全的,因此如果在更新容器时有更多线程可能访问容器,则必须有一个锁。如果您只是阅读,或者只有一个线程访问特定容器,那么无论如何您都是安全的。
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 2010-09-16
    • 2010-12-17
    • 2012-12-25
    • 1970-01-01
    相关资源
    最近更新 更多