1

3つのアトミック変数を比較して交換したい:

std::atomic<int> a;
std::atomic<int> expected;
std::atomic<int> new;

int expectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
int newValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

std::atomic_compare_exchange_strong_explicit(
    &a, 
    &expectedValue, 
    newValue, 
    std::memory_order_relaxed, 
    std::memory_order_relaxed);

しかし、変数と変数の読み取りexpectednew比較の間にa、別のスレッドが値を変更すると、現在のスレッドは以前の値で機能するため、コードを次のように変更します。

while(true)
{
    int expectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
    int newValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

    std::atomic_compare_exchange_strong_explicit(
        &a, 
        &expectedValue, 
        newValue, 
        std::memory_order_relaxed, 
        std::memory_order_relaxed);

    int newExpectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
    int newNewValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

    if(newExpectedValue == expectedValue && newNewValue == newValue)
        break;
}

私のコードは正しいですか?またはこれを行うためのより良い方法はありますか?

4

2 に答える 2

3

書き直された関数は、一貫性のない結果をもたらす可能性があります。expectedにロードした後newExpectedValue、 if をチェックする前に変更された場合はどうなりnewExpectedValue == expectedValueますか? ロード後、ロード前に変更した場合はどうnewなりますか?expectedexpectednew

これは、アトミックの使用方法ではありません。3 つの変数をアトミックに操作する必要がある場合は、ロックを使用して操作中にアクセスをシリアル化する必要があります。ここではミューテックスまたはスピンロックがより適切です。

于 2013-10-26T08:17:10.887 に答える
1

そもそもなぜexpectedとアトミックなのですか? new通常、あるスレッドで何らかの方法で新しい値を計算し、そのスレッドだけが新しい値を知っており、compare_exchange を実行します。同様に、 の値expectedは、そのスレッドが計算を開始する前の古い値ですが、予想される古い値は、その 1 つのスレッドにとってのみ重要です。

つまり、スレッド間で共有しないでくださいexpectednew

于 2013-10-26T08:42:33.580 に答える