简体   繁体   English

互斥锁的正确粒度

[英]Proper Granularity for Mutex Lock

I am working on a program that prints regex matches from several threads searching the filesystem and each thread adds its id to a queue and notifies the main thread that there are some threads to be removed from the thread pool which is a std::vector. 我正在开发一个程序,该程序从搜索文件系统的多个线程中打印正则表达式匹配项,每个线程将其id添加到队列中,并通知主线程有一些线程将从std :: vector线程池中删除。

At this point, I am unlocking and locking the mutex whenever I perform an operation on the resource to be protected. 此时,每当我对要保护的资源执行操作时,我便会解锁并锁定互斥锁。 It feels like I'm thinking of this all wrong and that I'm being way too granular. 感觉就像我在想这一切都是错的,而且我太细心了。 Would it be better to lock the mutex before entering the while loop, unlock it after popping the queue, and then locking it again before !finished_threads.empty() is called on the next iteration? 在进入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();
            }
        }
    }
}

You certainly have to keep the lock from the test for !empty() until you have removed the item from the queue. 在从队列中删除该项目之前,您当然必须保持对!empty()的测试锁定。 Otherwise several threads might try to remove the same item - perhaps the last one. 否则,多个线程可能会尝试删除同一项目-可能是最后一个。

I also see that the push_back at the start of the function is unprotected. 我还看到函数开始处的push_back不受保护。 If there might be several threads accessing the search_pool , it must be guarded as well. 如果可能有多个线程访问search_pool ,则也必须对其进行保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM