7

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;
        }
}
4

3 に答える 3

16

私は正しいですか?

いいえ。これにより、コピーが作成されて返されます。ただし、同期せずにそのコピーを作成するためにそれを読み取ると、未定義の動作でデータ競合が発生します。ミューテックスをロックしてローカル コピーを作成する必要があります。

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

または、エラーが発生しにくい RAII ロック タイプを使用します。

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

C++11 では、std::atomic<bool>複数のスレッドから単純な型へのより便利で効率的なアクセスを検討することができます。

于 2013-05-13T13:12:53.153 に答える
3

競合状態は、変数がヒープにあるかスタックにあるかとは関係ありません。競合状態とは、あるスレッドが変数 (メモリの場所) を変更し、別のスレッドが同じ変数を読み取りまたは変更している場合です。a の変更がアトミックであるという保証はない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;
}

std::atomic<>変更がアトミックであることを保証し、明示的なロックの必要性を回避するc++11 も導入されました。

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

c++11 が利用できない場合boost::atomicは v1.53.0 で導入され、ブーストにも同等boost::mutexの とboost::lock_guardがあります。

于 2013-05-13T13:13:18.250 に答える
1

はい、ロックが必要です

C++11 のメモリ モデルでは、値を読み取る別のスレッドと同時に値を書き込んでいるスレッドがあると、データ競合が発生します。これは、読み取りおよび/または書き込みの両方がアトミックではない可能性があるためです。

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

これを解決する簡単な方法はshutdownInProgress、atomic を作成することです。

static std::atomic<bool> shutdownInProgress;

アトミックにすると、どちらの関数にもロックはまったく必要ありません

于 2013-05-13T13:12:43.990 に答える