web-dev-qa-db-ja.com

条件が満たされたときにstd :: threadに自分自身を強制終了/停止させる

ワーカースレッドtWorkerがあるとします。これはBossの構築時に初期化され、bRetiredがtrueになるまでwork()を実行するように指示します。 _std::mutex_、mtxは、一部のデータ(vFiles)をロックし、tWorkerが作業しているときにそれを所有します。

tWorkerbRetiredになった後、trueを「自殺」する方法を教えてください。スレッドが実行を停止すると、mutexはどのように破棄されますか?

_std::thread_オブジェクトはいかなる方法でも中断できないことを読みました。スレッドに何もさせない(またはstd::this_thread::yield()を呼び出す)と、スレッドを強制終了するのと同じ効果がありますか?

_class Boss {
private:
    std::thread tWorker;
    std::mutex mtx;
    bool bRetired;
    std::vector< std::string > vFiles;

    void work() {
        while ( bRetired == false ) {
            // Do your job!
            mtx.lock();
            // ... Do something about vFiles ...
            mtx.unlock();
        }

        // tWorker has retired, commit suicide
        // ** How? **

        // Does this suffice if I want to "kill" the thread?
        std::this_thread::yield(); 
    }

public:
    Boss() {
        bRetired = false;
        tWorker = std::thread( &Boss::work, this );

        // Have worker do its job independently
        // **Bonus Question** : Should this be tWorker.join() or tWorker.detach()?
        tWorker.detach();
    }

    retire() {
        bRetired = true;
    }
}
_

メモ

  • ワーカースレッドは、いったん終了すると、再度開始することはできません。
  • ワーカースレッドは、メインスレッドの実行を中断せずにバックグラウンドで動作します。
10
alxcyl

std::thread::yield() の呼び出しは不要であり、呼び出しスレッドを強制終了しません。

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

スレッドを終了するには、関数を終了するだけです。

2つのスレッドが同じメモリロケーションにアクセスでき、それらのスレッドの1つがそれを変更しているため、bRetiredの使用は正しくないことに注意してください。これは未定義の動作です。また、別のスレッドである関数retire()で行われた変更は、run()を実行するスレッドには表示されません。使用 _atomic<bool>_ for原子性と可視性。

join() がコンストラクター内で使用された場合、コンストラクターはスレッドが終了するまで戻りません。これは、retire()を呼び出すことができないため、発生しません。オブジェクトは使用できません(コンストラクターが返されなかったため)。スレッドの終了と同期する必要がある場合は、detach()関数ではjoin()ではなくretire()を使用してください。

_void retire() {
    bRetired = true;
    tWorker.join();
}
_

RAIIを使用してmutexes( _std::lock_guard_ など)を取得し、常に解放されるようにします。 mutexは、スコープ外になると破棄されます。この場合は、その包含クラスが破棄されます。

5
hmjd

BRetiredがtrueになった後、tWorkerを「自殺」する方法を教えてください。

制御フローにスレッド関数を終了させます。そのstd::this_thread::yield()呼び出しは不要です。

スレッドが実行を停止すると、ミューテックスはどのように破棄されますか?

そのミューテックスはBossクラスのメンバーです。オブジェクトが破棄されるときに、Bossのデストラクタで破棄されます。

Std :: threadオブジェクトを中断することはできません。

C++ APIは、任意のスレッドを終了する手段を提供しません。意図したとおり、スレッドに終了を指示し、終了するまで待機する方法が必要です。

スレッドに何もさせない(またはstd :: this_thread :: yield()を呼び出す)と、スレッドを強制終了するのと同じ効果がありますか?

番号。

ただし、bRetired変数には競合状態があります。 std::atomic<bool>または、そのmutexがロックされている場合にのみ、読み取りと変更を行う必要があります。

6