2017-10-21 6 views
1

私は物理エンジンを作成しようとしています(楽しみのため)、私はマルチスレッド化したいと思います。
私はミューテックスの基本を理解しています(1つのスレッドは、一度にガーディングするリソースを変更できますが、スレッドレベルではなくクラスレベルであるなど)。私はメンバ変数のためにアトミックを使用しない方が望ましいです(複雑な操作を行っている場合は、実行の途中で変更されないようにするか、単に変数をコピーすることをお勧めします) )。あるスレッドで複数のオブジェクトをロックするにはどうすればよいですか?

この概念に続いて、(簡体字)Vectorクラスは、次のようになります。

class vector 
{ 
    float x_, y_; 
    std::mutex guard_; 
}; 

私はそれを使用したい場合は、どのように彼らはロックされなければなりませんか?

void foo(vector v1, vector v2) 
{ 
    std::lock_guard<std::mutex>(v1.guard_); 
    std::lock_guard<std::mutex>(v2.guard_); 
    // Do stuff with v1 and v2... 
} 

このようにしますか?これは実際に両方のオブジェクトを保護しますか?

TL; DR複数のオブジェクトが同じスレッドで操作されている場合、どのようにmutexをロックするべきですか? (アトミックやコピーを使用しないで)

+1

は、オブジェクトにアクセスするすべてのコードは、使用する前にそれらをロックと仮定して、よさそうです。 [デッドロック](https://en.wikipedia.org/wiki/Deadlock)に注意してください。これは、複数のオブジェクトをロックするときによく発生します。 – hnefatl

+0

ミューテックスはおそらく2つの 'float'と同じくらい大きいので、コピーに基づいていくつかの仮説的解決法に比べてメモリを節約しているとは限りません。 –

+1

ミューテックスは、オブジェクト(変数)ではなくコードパスを保護します。これは、1つ以上のコードパスを保護するサイズ効果です。 –

答えて

3

2つのスレッドが同じ2つのロックを反対の順序で実行しようとすると、デッドロックが発生します。これは古典的なdining philosophersの問題によって示されています。

標準的な解決策は、固定された任意の順序をロックに適用し、すべての場合に最初に「下位」を取ることです。 user3290797の答えは、これを行うための正しいライブラリ機能を提供します。

5
std::lock_guard<std::mutex>(v1.guard_); 
std::lock_guard<std::mutex>(v2.guard_); 

別のスレッドが異なる順序で同じ2つのミューテックスをロックしようとした場合、デッドロックの危険性があるこの方法です。

デッドロックを回避し、例外の安全性を確保する両方のために、あなたが最初に一度に両方のミューテックスをロックして、コンストラクタを採用lock_guard年代にすでにロックされたミューテックスを渡す必要があります:

std::lock(v1.guard_, v2.guard_); 
std::lock_guard<std::mutex> guard1(v1.guard_, std::adopt_lock); 
std::lock_guard<std::mutex> guard2(v2.guard_, std::adopt_lock); 

C++ 17あなたの中にstd::scoped_lockstd::lock_guardに類似したクラスが、複数のミューテックスを所有する能力を使用することができます。

std::scoped_lock guard{v1.guard_, v2.guard_}; 
関連する問題