C++セミナー(上級)マルチスレッド処理

HOME->講習会->プログラミングセミナー->C++セミナー(上級)


ひと昔前は,シングルコアCPUしかなかったので,シングルスレッドによるプログラミングが一般的でしたが,現在はマルチコアCPUが増えたので,マルチスレッドによるプログラミングが登場しました.ここでは,C++でのマルチスレッド処理について紹介します.

目次

threadライブラリ
thread放棄
thread待機

threadライブラリ

C++では,マルチスレッド処理を行うためのライブラリとして「thread」があります.一例を以下に示します.

#include <iostream>
#include <thread>

void function(int a)
{
    std::cout << a << ": " << std::this_thread::get_id() << std::endl;
}

int main()
{
    std::cout << "m: " << std::this_thread::get_id() << std::endl;
    std::thread th1(&function, 1);
    std::thread th2(&function, 2);
    th1.join();
    th2.join();
}

上記をコンパイルするときには,コンパイルオプションとして,「-pthread」を付けてください.

g++ thread.cpp -pthread

処理を実行すると以下のような結果が得られます.結果は実行するたびに異なります.

m: 140418944500544
1: 140418944485120
2: 140418936092416

処理の内容としては,「std::this_thread::get_id()」で現在処理を行っているスレッドIDを取得して表示しています.メイン関数のID,1を渡したスレッドのID,2を渡したスレッドのID,すべてのIDが異なることがわかると思います.これで,正しくマルチスレッド処理ができていることがわかります.「14-15行目」では,「join()」メソッドを呼び出しています.これは,マルチスレッド処理で実行した処理が終了するまで待機する処理になります.この処理を行わなかった場合は,メイン処理が終了したときに,強制的に他のスレッドの処理もエラー終了してしまうため,必ず呼び出しましょう.

thread放棄

上記では,他のスレッドの処理が終了するまで待機する「join()」メソッドを紹介しましたが,場合によっては,メイン処理が終了しても処理をし続けてほしい場合があります.このような場合には,「detach()」メソッドを使用して,thread管理を放棄する必要があります.なお,threadが宣言されたブロックが棄却される場合には,「join()」もしくは,「detach()」を呼び出さなければいけません

#include <iostream>
#include <thread>

void function(int a)
{
    for(int i=0; i<100; i++) std::cout << a << ": " << i << std::endl;
}

int main()
{
    std::cout << "m: " << std::this_thread::get_id() << std::endl;
    std::thread th1(&function, 1);
    th1.detach();
}

ただし,メイン関数の処理が終了すると強制的にすべてのスレッドの処理が終了させられるので,上記のプログラムでは,99まで表示されません.threadを宣言したブロックが棄却されても処理が実行はされるというような認識でいましょう.

thread待機

場合によっては,処理を数秒間待機させたい場合があります.そのような場合には,以下のようにします.

#include <iostream>
#include <thread>
#include <chrono>

int main()
{
    for(int i=0; i<10; i++){
        std::cout << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

上記のプログラムを実行すると0~9まで1秒おきに出力されます.「std::this_thread::sleep_for(std::chrono::seconds(1))」が,スレッドをスリープさせているプログラムになります.今回の場合は,1秒間のスリープですが,「seconds」を「nanoseconds」や「milliseconds」などに変更することで,ナノ秒やミリ秒単位の待機も可能です.「std::chrono」については,「C++セミナー(上級)処理時間計測」を参照してください.