スレッド/ミューテックスマネージャーを実装するための最近の取り組みは、75%のCPU負荷(4コア)になりましたが、実行中の4つのスレッドはすべてスリープ状態か、ミューテックスビーのロックが解除されるのを待っていました。
特定のクラスは、ここに完全に掲載するには大きすぎますが、原因を2つのミューテックスのデッドロックセーフな取得に絞り込むことができます。
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
クラスの別の部分では、std::condition_variable
withwait()
とnotify_one()
onmutex1
を使用して、一部のコードを同時に選択的に実行します。
への簡単な変更
std::unique_lock<std::mutex> lock1( mutex1 );
std::unique_lock<std::mutex> lock2( mutex2 );
CPU使用率を通常の1〜2%に下げました。
私は信じられません、std::lock()
機能はその非効率的です。これはg++4.6.3のバグでしょうか?
編集:(例)
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mutex1, mutex2;
std::condition_variable cond_var;
bool cond = false;
std::atomic<bool>done{false};
using namespace std::chrono_literals;
void Take_Locks()
{
while( !done )
{
std::this_thread::sleep_for( 1s );
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
std::this_thread::sleep_for( 1s );
lock1.unlock();
lock2.unlock();
}
}
void Conditional_Code()
{
std::unique_lock<std::mutex> lock1( mutex1, std::defer_lock );
std::unique_lock<std::mutex> lock2( mutex2, std::defer_lock );
std::lock( lock1, lock2 );
std::cout << "t4: waiting \n";
while( !cond )
cond_var.wait( lock1 );
std::cout << "t4: condition met \n";
}
int main()
{
std::thread t1( Take_Locks ), t2( Take_Locks ), t3( Take_Locks );
std::thread t4( Conditional_Code );
std::cout << "threads started \n";
std::this_thread::sleep_for( 10s );
std::unique_lock<std::mutex> lock1( mutex1 );
std::cout << "mutex1 locked \n" ;
std::this_thread::sleep_for( 5s );
std::cout << "setting condition/notify \n";
cond = true;
cond_var.notify_one();
std::this_thread::sleep_for( 5s );
lock1.unlock();
std::cout << "mutex1 unlocked \n";
std::this_thread::sleep_for( 6s );
done = true;
t4.join(); t3.join(); t2.join(); t1.join();
}