私がコードで見た1つの問題は、特に例外が発生したときに問題につながることです。
obj1->obtainMutex(); //Should I create a mutex for each object so that I could obtain mutex when I am going to update fields for obj1?
pthread_mutex_unlock(&mutexA); //release mutex for unordered_map so that other threads could access other object
obj1->field1 = 1;
performOperation(obj1);
performOperationが例外をスローすると、obj1-> releaseMutex();例外がスローされます。オブジェクトがロックされたままになり、将来的にはデッドロックにつながる可能性があります。 あなたが例外を使用しない場合でも、performOperationで使用するライブラリコードがあります。または、あなたが将来間違って将来間に合って、戻り値を挿入して、以前に所有していたすべてのロックを解除することを忘れるかもしれません...
pthread_mutex_lockとpthread_mutex_unlockの呼び出しは同じです。
ロック/ロック解除にRAIIを使用することをおすすめします。
I.e.コードは次のようになります。
typedef std::unordered_map<string, classA*>MAP1;
MAP1 map1;
Lock mapLock(&mutexA); //automatci variable. The destructor of the Lock class
//automatically calls pthread_mutex_unlock in its destructor if it "owns" the
//mutex
if(map1.find(id) == map1.end())
{
classA* obj1 = new classA;
map1[id] = obj1;
Lock objLock(obj);
mapLock.release(); //we explicitly release mapLock here
obj1->field1 = 1;
performOperation(obj1); //takes some time
}
Ie.いくつかの最小限のRAAIスレッディングサポートのリファレンスについては、Andrei Alexandrescu(see here)の「Modern C++ design:generic programming and design patterns applied」を参照してください。他のリソースもあります(here)
最後に、コードでわかるもう1つの問題について説明します。より正確には、obtainMutexとreleaseMutexをメソッドとして持ち、それらを明示的に呼び出すことで見られる問題です。スレッド1がマップをロックし、オブジェクトを作成してobtainMutexを呼び出し、マップをロック解除するとします。別のスレッド(スレッド2と呼ぶことができます)は実行ロックがスケジュールされます。マップはイテレータをオブジェクトのmap1 [id]に取得し、pObjectのreleaseMutex()を呼び出します(つまりコードが試みないバグobtainMutexを最初に呼び出す)。スレッド1はスケジュールされ、ある時点でreleaseMutex()も呼び出されます。オブジェクトは一度ロックされていますが、二度リリースされました。私が言っていることは、オブジェクトロックインターフェイスのロックを解除しない誤った使用が起こっている可能性があるため、例外が発生したときにコールが常に正しくペア設定されていることを確認する作業が難しくなるということです。また、スレッド2は、マップから取得したpObjectを削除し、マップから消去することもできます。スレッド1は、すでに削除されたオブジェクトを持つ作業に進みます。
RAIIを使用すると、コードをわかりやすく(私たちのバージョンを比較するとさらに短くなります)、上で列挙したいくつかの問題に多く役立ちます。
' - > obtainMutex()'が作成される前に別のスレッドがobj1に到達することができない限り、デッドロックが発生する領域はありません。言い換えれば、読み書きのために 'map1'にアクセスする前に' mutexA'をロックしている限り、あなたはOKです。しかし、 'pthread_mutex_unlock(&mutexA)'をマップ内のオブジェクトの内容に基づいてマップのidが変更されない限り、1行上に移動すると思います。 – milkypostman
'map1'への更新のために、複数のスレッドを介して' map'に格納されたオブジェクトがアクセスされていますか?オブジェクトをスレッドセーフなものにするほうが良いのではないですか?その言葉を残念に思っています---あなたのコードは 'obj1-> obtainMutex'ですか? – Jaywalker
私は数年前にMSVCで作業していましたが、標準ライブラリのマルチスレッド版がありました。スレッドセーフなバージョンのstlを手に入れることができれば、コンテナ単位のmutex mutexA – davka