2013-05-13 7 views
5

C++コンパイラがローカル変数を処理する方法を理解していれば、IsShutdownInProgress()は静的変数shutdownInProgressがスタックに配置されるため、ロックを必要としません。私は正しいですか?オブジェクト値を返すときのミューテックス

class MyClass 
{ 
    private: 
     // Irrelevant code commented away 
     static pthread_mutex_t mutex; 
     static bool shutdownInProgress; 
    public: 
     static void ShutdownIsInProgress() 
     { 
      pthread_mutex_lock(mutex); 
      shutdownInProgress = true;     
      pthread_mutex_unlock(mutex); 
     } 

     static bool IsShutdownInProgress() 
     { 
      // pthread_mutex_lock(mutex); 
      // pthread_mutex_unlock(mutex); 
      return shutdownInProgress; 
     } 
} 

答えて

7

アムIのために、すべてのロックを必要としない作る場合

static std::atomic<bool> shutdownInProgress; 

正しい?

いいえこれは、そのコピーを返します。そのコピーを同期せずに読み取ると、のデータ競合が未定義の動作をします。あなたは、C++ 11では

static bool IsShutdownInProgress() 
{ 
    lock_guard lock(mutex); 
    return shutdownInProgress; 
} 

かもしれません:

static bool IsShutdownInProgress() 
{ 
    pthread_mutex_lock(mutex); 
    bool result = shutdownInProgress; 
    pthread_mutex_unlock(mutex); 
    return result; 
} 

または、以下のエラーが発生しやすいRAIIロックタイプを使用して:あなたは、ミューテックスロックでそれのローカルコピーを作成する必要がありますstd::atomic<bool>は、複数のスレッドから単純な型にアクセスする方が便利で、おそらくより効率的であると考えてください。

1

はい、それはロック

C++ 11のメモリモデルは、いずれかのスレッドがそれを読んで、別のスレッドと同時に値を書いている場合は、データレースを持って述べている必要があります。これは、読み取りおよび/または書き込みの両方がアトミックでない可能性があるためです。

この場合、関数からローカルを返しますが、コンパイラはshutdownInProgressの値をコピーする必要があります。ShutdownIsInProgress()を呼び出す別のスレッドによって同時に変更される可能性があります。

この問題を解決する簡単な方法は、shutdownInProgressを作ることである原子:あなたは、それは原子、どちらかの機能

2

競合条件は、変数がヒープ上にあるかスタック上にあるかとは無関係です。競合状態とは、あるスレッドが変数(メモリ位置)を変更していて、別のスレッドが同じ変数を読み込んだり変更している場合です。 boolの変更がアトミックであり、投稿されたコードに競合状態が存在するため、未定義の動作であるという保証はありません。

修正がミューテックスを保持しboolの値を格納する変数を返すようになるであろう:

static bool IsShutdownInProgress() 
{ 
    pthread_mutex_lock(&mutex); 
    bool result = shutdownInProgress; 
    pthread_mutex_unlock(&mutex); 
    return result; 
} 

C++ 11に導入std::mutexstd::lock_guard使用することができ、lock_guardの使用戻りのためbool値を格納する一時変数の必要性を回避する。

static std::mutex mtx_; 
static bool IsShutdownInProgress() 
{ 
    std::lock_guard<std::mutex> lk(mtx_); 
    return shutdownInProgress; 
} 

C++ 11にも導入されたMを確実にするstd::atomic<> odificationはアトミックであると明示的なロックの必要性を回避:

static std::atomic<bool> shutdownInProgress; 
static bool IsShutdownInProgress() 
{ 
    return shutdownInProgress; 
} 

C++ 11はv1.53.0に導入され、またboost::mutex and boost::lock_guard相当してい後押しされたboost::atomicに使用できない場合。

関連する問題