2011-09-11 24 views
7

boost :: upgrade_lockの正しい使い方を教えてください。デッドロックboost :: shared_lockを排他ロックにアップグレードする

//Global 
typedef boost::shared_mutex Mutex; 
typedef boost::shared_lock<Mutex> ReadLock; 
typedef boost::upgrade_lock<Mutex> UpgradeLock; 
typedef boost::upgrade_to_unique_lock<Mutex> WriteLock; 
Mutex sharedMutex; 


//Multi threaded reader and writer 
{ 
    ReadLock read(sharedMutex); 

    for (int ii = 0; ii < vec.size(); ++ii) { 
     Element e = vec[ii]; 

     if (e.needsUpdating()) { 
      UpgradeLock upgrade(sharedMutex); 

      WriteLock write(upgrade) 

      //Do stuff 
     } 
    } 
} 

私は、アップグレードの前にread.unlock()で読み込みロックを解除した場合にそれがデッドロックしないで次のコードの結果。しかし、これは必要ではないと思われますか?

答えて

9

クラス(UpgradeLockableの概念を実装しています)では、1つのスレッドが共有ロックとアップグレード可能(または一意の)ロックの両方を取得しようとすべきではありません。 UpgradeLockableにはいつでもN個の共有ロック(lock_shared)とアップグレード可能なロック(lock_upgrade)があります。アップグレード可能なロックは、それが排他的な所有者になるまでブロックする一意のロックになるように要求できます。これにより、すべての共有ロックが解放される必要があります。共有ロックを一意のロックに変換すること、または共有ロックをアップグレード可能なロックに変換することは不可能です。

アップグレード可能なロックは、強さを増強する特別な特権を持つだけで排他的ではありません(他の共有ロックを保持できることに注意してください)。残念ながら、複数のアップグレード可能なスレッドは同時に使用できません。

同じスレッドがデッドロックするlock_sharedlock_upgradeを使用しようとしています。以下のように書き換えることができます。デッドロックは発生しませんが、一度に1つしかアップグレードロックを保持しないため、すべての読者にとっては単一の競合ポイントです。この場合、他の関数によっては、shared_mutexの複雑さが必要ないかもしれません。ただし、他の機能が引き続き共有ロックを取得している場合は、以下の内容が期待どおりに機能します。

//Multi threaded reader and writer 
{ 
    // Only 1 thread can pass this. Other shared locks are also valid 
    UpgradeLock read(sharedMutex); 

    for (int ii = 0; ii < vec.size(); ++ii) { 
     Element e = vec[ii]; 

     if (e.needsUpdating()) { 
      // Blocks here until all shareds are released 
      WriteLock write(upgrade) 

      //Do stuff 
     } 
    } 
} 
+0

残念ながら、ループを同時に入力できるように複数のリーダーが必要なので、アップグレードロックを使用することはできません。説明をありがとう。 –

関連する問題