C++11でスレッドを終了する方法:std::promiseとstd::futureを使った安全な実装
C++11でスレッドを終了するには?
C++11には、スレッドを外部から直接強制終了するための標準的な仕組みが用意されていません。無理にスレッドを中断すると、リソースリークやデッドロックといった深刻な問題を引き起こす恐れがあるため、「スレッド自身に終了を判断させる」設計が推奨されます。
そこで活躍するのが、std::promiseとstd::futureを組み合わせた手法です。std::future<void>をスレッド関数に渡しておき、futureに値がセットされた(=シグナルが届いた)時点でスレッドを終了させます。実際のデータを渡す必要がない場合は、void型のオブジェクトを使うだけで「終了シグナル」として機能させられます。
手順1:promiseオブジェクトを作成する
まず、次の構文でpromiseオブジェクトを生成します。
std::promise<void> exitSignal;
手順2:main関数でfutureオブジェクトを取得する
続いて、作成したpromiseオブジェクトから、それに関連付けられたfutureオブジェクトを取得します。
std::future<void> futureObj = exitSignal.get_future();
手順3:スレッド生成時にfutureを渡す
最後に、スレッドを作成する際にfutureオブジェクトを渡します。所有権の移動にはstd::moveを使用します。
std::thread th(&threadFunction, std::move(futureObj));
サンプルコード
以下は、上記の手順を実装した完全なサンプルコードです。メインスレッドは7秒間待機した後、promiseに値をセットしてワーカースレッドへ終了を通知します。
#include <thread>
#include <iostream>
#include <assert.h>
#include <chrono>
#include <future>
using namespace std;
void threadFunction(std::future<void> future){
std::cout << "Starting the thread" << std::endl;
// シグナルが届くまでループを継続
while (future.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout){
std::cout << "Executing the thread....." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 500ミリ秒待機
}
std::cout << "Thread Terminated" << std::endl;
}
int main(){
std::promise<void> signal_exit; // promiseオブジェクトを作成
std::future<void> future = signal_exit.get_future(); // futureオブジェクトを取得
std::thread my_thread(&threadFunction, std::move(future)); // スレッドを開始し、futureをムーブ
std::this_thread::sleep_for(std::chrono::seconds(7)); // 7秒間待機
std::cout << "Threads will be stopped soon...." << std::endl;
signal_exit.set_value(); // promiseに値をセットして終了を通知
my_thread.join(); // メインスレッドと合流
std::cout << "Doing task in main function" << std::endl;
}
実行結果
Starting the thread Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Executing the thread..... Threads will be stopped soon.... Thread Terminated Doing task in main function
動作のポイント
- wait_forによるポーリング: ワーカースレッド側は
future.wait_for()で短いタイムアウト付きの状態確認を行い、タイムアウトしている間は処理を続行します。 - set_value()で終了を通知: メインスレッドが
signal_exit.set_value()を呼び出すと、futureの状態がreadyに変化し、whileループを抜けてスレッドが正常終了します。 - join()を忘れずに: 最後に
join()でスレッドの完了を待ち合わせることで、リソースを安全に解放できます。
このように、C++11では強制終了ではなく、promise/futureによる協調的な終了通知を行うことで、安全かつ確実にスレッドを停止させることができます。
-
Androidでスレッドを作成する方法を徹底解説!初心者向けサンプルコード付き
Androidにおけるスレッドとは?スレッドとは、軽量なサブプロセスのことであり、UI(ユーザーインターフェース)を中断させることなくバックグラウンド処理を実行するために使用されます。Androidアプリ開発では、時間のかかる処理をメインスレッドから切り離すことで、アプリの応答性や操作性を維持することができます。本記事では、実際のサンプルコードを交えながら、Androidでスレッドを作成する方法をステップごとに分かりやすく解説します。手順1:Android Studioで新規プロジェクトを作成するまず、Android Studioを起動し、メニューから「File」→「New Project」を
-
PythonのTkinterでスレッドを使う方法|threadingモジュールによる非同期処理の基本
Tkinterでは、スレッド(Threading)を活用することで、複数の関数を同時に実行できます。これにより、アプリケーション内の処理を非同期で動かすことが可能になります。 Pythonでスレッドを使用するには、まずthreadingモジュールをインポートし、そのThreadクラスを継承した新しいクラスを定義します。そして、クラス内でrunメソッドをオーバーライドし、実行したい処理をその中に記述します。 つまり、スレッドを使えば複数の作業を並行して進めることができます。Tkinterアプリケーションでスレッドを実現する際は、Thread()関数を利用します。 ここでは、「一定時間スリープした