2016-12-20 49 views
0

我正在從一個程序打印正則表達式匹配從幾個線程搜索文件系統和每個線程將其ID添加到隊列並通知主線程有一些線程要從線程池中刪除這是一個std :: vector。正確的Mutex鎖的粒度

此時,我解鎖並鎖定互斥鎖,只要我對要保護的資源執行 操作。感覺就像我是 ,認爲這一切都是錯誤的,並且我的方式太細緻。 最好是在進入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

你一定要保持從測試鎖定爲!empty(),直到刪除隊列中的項目。否則,幾個線程可能會嘗試刪除相同的項目 - 可能是最後一個。

我也看到在函數開頭的push_back是不受保護的。如果可能有多個線程訪問search_pool,則它也必須被保護。

+0

哦,這很有道理。在調用Run()之前沒有線程訪問thread_pool。是否有必要用互斥鎖來鎖定它? – CanadaIT

+0

標準容器不是線程安全的,所以如果更多線程在更新時可能訪問容器,則必須有鎖。如果您只是閱讀,或者只有一個線程訪問特定的容器,則無論如何您都是安全的。 –