0

2 つの質問があります。1 つは共有データを変更し、もう 1 つは共有データを操作する 2 つのスレッドについて考えてみましょう。どちらのスレッドも、データを処理する前にミューテックスを取得します。

データを操作するスレッドが、最初のスレッドによって行われた変更を常に確認できるようにするにはどうすればよいですか? 一連の取得/解放フェンスが必要ですか、それともミューテックスを使用してスレッドを暗黙的に同期しますか? ミューテックスを使用しない場合 (ただし、排他的アクセスを保証する場合) はどうなりますか?

そして:フェンスは、インターリーブ/フォローアップのアトミック操作なしで実際に何かをしますか(atomic_boolにフラグを格納する、「準備完了」などを通知するなど)?

ユースケースは次のとおりです。

void func()
{
    std::atomic_bool quit = false;

    std::vector<float> data(100);
    std::mutex m;

    std::thread one([&]() 
        {
            while (!quit.load(std::memory_order_relaxed))
            {
                std::unique_lock<std::mutex> lock(m, std::try_to_lock);

                if (lock.owns_lock())
                {
                    for (int i = 0; i < data.size(); ++i)
                    {
                        data[i] = std::rand();
                    }

                    std::atomic_thread_fence(std::memory_order::memory_order_release);
                }
            }
        }
    );

    std::thread two([&]() 
        {
            while (!quit.load(std::memory_order_relaxed))
            {
                std::unique_lock<std::mutex> lock(m, std::try_to_lock);

                if (lock.owns_lock())
                {
                    // guaranteed that any changes from thread one to 'data' is seen after this fence?
                    std::atomic_thread_fence(std::memory_order::memory_order_acquire);

                    auto res = std::accumulate(data.begin(), data.end(), 0);
                    std::cout << "Accumulated result is: " << res << std::endl;
                }
            }
        }
    );

    fgetc(stdin);

    quit.store(true);
    one.join();  two.join();
}
4

2 に答える 2

1

データを操作するスレッドが、最初のスレッドによって行われた変更を常に確認できるようにするにはどうすればよいですか? 取得/解放フェンスのセットが必要ですか? それとも、ミューテックスを使用してスレッドを暗黙的に同期しますか?

Mutex がすべての作業を行います。追加のメモリ フェンスは必要ありません。

ミューテックスを使用しない場合 (ただし、排他的アクセスを保証する場合) はどうなりますか?

これは、 を保証するメカニズムに依存していますexclusive access。ほとんどのメカニズムでは、追加のフェンスを使用する必要はありません。[厳密に言えば、定義による排他的アクセスは、対応するメモリ順序を意味します。]

アクセスが実際に並行である場合はメモリ フェンスが必要になる場合がありますが、他の変数にアクセスする場合は、何らかの不変条件が確実に守られるようにする必要があります。

フェンスは、インターリーブ/フォローアップのアトミック操作なしで実際に何かを行いますか?

フェンスはアトミック操作のみに限定されません。実際には、フェンスは単なるバリアであり、フェンスの前と後の 2 つのグループにすべてのアクセス(フェンスのタイプに応じてストア、ロード、またはその両方) を分割します。

于 2015-11-16T13:10:01.987 に答える
0

フェンスは、ハードウェアが内部キャッシュをメイン メモリと同期させるためのシグナルにすぎません。事実上、それらは実行バリアであり、このバリアを通過する前にメモリ同期を要求します。したがって、名前。

于 2015-11-16T16:02:52.293 に答える