1

同僚と私は、スピンロック ミューテックスをstd::atomic_flagで実装したいが、そのスピンロックを while(true) ではなく

while(true)
{
     cnt=0;
     while (cnt<yieldAfterTries)
     {
        //try to get lock
        cnt++;
     }
     std::this_thread::yield();

     // if got lock do work and then break;
}     

基本的なアイデアは、スレッドがリアルタイムの優先度を持っていても、しばらくすると生成されるため、「非常に長い間」他のスレッドをブロックできないということです...しかし、 std::yield の仕様を見たとき、それは提案であり、強制的なものではありません。

スレッドの実行を再スケジュールするためのヒントを実装に提供し、他のスレッドを実行できるようにします。

http://en.cppreference.com/w/cpp/thread/yield

それで、それは問題になる可能性がありますか?

4

2 に答える 2

6

私はあなたのコードと非常によく似たコードを書き、yield競合の激しい状況下での呼び出しの影響を測定しました。yieldこのように を使用すると、システム全体のスループットが向上することがわかりました。

実際の仕様は、あなたが引用したものと精神的に違いはありませんが、30.3.2 [thread.thread.this]、段落 2 および 3 からの正確な仕様は次のとおりです。

void this_thread::yield() noexcept;

効果:実装に再スケジュールの機会を提供します。

同期:なし。

実装yieldがノーオペレーションとして実装されている場合 (たとえば)、これはコードのパフォーマンスのみに影響し、正確性には影響しません。失敗したスピンロックは、yield. ただし、不必要に CPU を占有する可能性が高くなり、システム全体のパフォーマンスが低下します。

于 2013-01-18T17:38:10.347 に答える
1

スピンロックは OS スケジューラによって自動的にプリエンプトされるため、このコードは不要になります。OS は、1 つのスレッドに時間がかかると、自動的に別のスレッドに切り替えます。これが、yield がヒントである理由です。たとえば、Linux の Completely Fair Schedular では、yield の呼び出しにより、スケジューラがスレッドを修正しようとして、時間の公平な配分が得られないため、不必要なコンテキスト スイッチが頻繁に発生します。

スピンロックを取得しようとしても何もブロックされません。スピンロックを保持しているだけで、他のものがブロックされます。

于 2013-01-18T15:49:10.320 に答える