ミューテックス(std::mutex)でlockする

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

以前別の記事で、Win32APIのCreateMutexを使ってC++でMutexで排他するというのをやったが、今回は標準ライブラリというのを使ってやってみる。

実験コード

今回の肝の「Mutex」は、冒頭のstd::mutex mtx;の部分。

mtx.lock();でロックをかけ、mtx.unlock();でロックを解除する。

実験① mutexをかけて排他する

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

static std::thread th_a;
static std::thread th_b;

int main()
{
    int param = 0;
    th_a = std::thread([&param]
        {
            mtx.lock(); // ロックを取得する

            std::cout << "+ スレッドA開始" << std::endl;

            for (size_t i = 0; i < 50; i++)
            {
                std::cout << "  スレッドA実行中..." << i << std::endl;
            }

            std::cout << "- スレッドA終了" << std::endl;

            mtx.unlock(); // ロックを手放す

        });

    th_b = std::thread([&param] 
        {
            mtx.lock(); // ロックを取得する

            std::cout << "+ スレッドB開始" << std::endl;

            for (size_t i = 0; i < 50; i++)
            {
                std::cout << "  スレッドB実行中..." << i << std::endl;
            }

            std::cout << "- スレッドB終了" << std::endl;

            mtx.unlock(); // ロックを手放す
        });

    // プログラム終了時にはjoinで終わるのを待つ
    th_a.join();
    th_b.join();
}

出力

ちゃんと、Aが終わった後にBが始まる感じになってくれる。

+ スレッドA開始
  スレッドA実行中...0
  スレッドA実行中...1
  スレッドA実行中...2
  スレッドA実行中...3
  スレッドA実行中...4
  スレッドA実行中...5
  スレッドA実行中...6
  スレッドA実行中...7
  スレッドA実行中...8
  スレッドA実行中...9
- スレッドA終了
+ スレッドB開始
  スレッドB実行中...0
  スレッドB実行中...1
  スレッドB実行中...2
  スレッドB実行中...3
  スレッドB実行中...4
  スレッドB実行中...5
  スレッドB実行中...6
  スレッドB実行中...7
  スレッドB実行中...8
  スレッドB実行中...9
- スレッドB終了

実験② mutexなしでやってみる

同じコードの、スレッドAとBのmtx.lock();でロックをかけ、mtx.unlock();でロックを解除する部分をコメントアウトしてみる。

結果

スレッドAとBの出力が入り交ざった感じになる。

+ スレッドB開始+ スレッドA開始

  スレッドB実行中...  スレッドA実行中...0
0
  スレッドA実行中...1
  スレッドA実行中...2
  スレッドB実行中...1
  スレッドA実行中...3
  スレッドB実行中...2
  スレッドA実行中...4
  スレッドA実行中...5
  スレッドB実行中...3
  スレッドA実行中...6
  スレッドB実行中...4
  スレッドA実行中...7
  スレッドB実行中...5
  スレッドA実行中...8
  スレッドB実行中...6
  スレッドB実行中...7
  スレッドA実行中...9
  スレッドB実行中...8
- スレッドA終了
  スレッドB実行中...9
- スレッドB終了

思ったこと(本題には関係ない)

CreateMutex()というWin32APIには、マイクロソフトのドキュメントがあるが、 std::mutexにはマイクロソフトのドキュメントはなさそうに見える。

これって、std::なんとかは、マイクロソフトが決めた決まり?ではなく、他のところで決められた規格?だからなのか?

↓chatGPTに聞いてみた。なるほど、、、

User
C++ 標準ライブラリ とは何ですか?
ChatGPT
C++ 標準ライブラリ(C++ Standard Library)は、C++プログラミング言語において標準で提供されているライブラリであり、共通のデータ構造、アルゴリズム、入出力処理、数学関数、文字列処理、ファイル処理など、一般的なプログラミングタスクをサポートする機能が含まれています。これはC++の公式な仕様で規定されており、プログラマが標準ライブラリを利用して効率的でポータブルなコードを書くのに役立ちます。

標準ライブラリは主に次の部分から構成されています:

C++標準テンプレートライブラリ(STL):データ構造やアルゴリズムなどのコンテナやアルゴリズムを提供する。例えば、std::vector、std::list、std::algorithmなどが含まれます。

入出力ストリームライブラリ:std::cout、std::cinなどのストリームを操作するためのクラスや関数が含まれています。

文字列ライブラリ:文字列の処理や変換に関する機能が提供されています。例えば、std::stringやstd::getlineなどがあります。

数学関数ライブラリ:数学的な計算を行うための関数が提供されています。例えば、std::sin、std::cos、std::sqrtなどがあります。

アロケータとメモリ管理:メモリの動的な確保・解放を行うためのアロケータや関連するクラスが含まれています。

これらの標準ライブラリの要素は、std 名前空間に封じ込められており、例えば std::cout や std::vector のように std:: を接頭辞として使用してアクセスします。これにより、異なる名前空間の要素との名前の衝突を避けることができます。

User
C++ 標準ライブラリは、なにかの団体が決めたものですか?
ChatGPT
はい、C++標準ライブラリは、ISO(International Organization for Standardization、国際標準化機構)によって定められた標準規格に基づいています。C++の最初の標準化は、1998年にISO/IEC 14882:1998として行われ、その後も新しい機能や改良が加えられながら、標準が進化しています。

C++標準委員会(ISO C++ Standards Committee)は、C++の標準化に関する作業を行うために設立されており、世界中のプログラマや業界の専門家が参加しています。彼らは、C++言語仕様や標準ライブラリの進化について議論し、提案を審査し、新しいバージョンの標準を策定します。

標準委員会は、プログラミング言語C++の進化に対応する形で、新しい機能や改良を取り入れながら、言語仕様や標準ライブラリを更新しています。このプロセスは、広範なコミュニティの協力と専門家の意見の集約を通じて進められています。

User
C++標準ライブラリの、Windows上での実装は、Win32APIが使われていますか?
ChatGPT
C++標準ライブラリの実装は、特定のプラットフォームによって異なります。Windows上でのC++標準ライブラリの実装は、通常、Win32APIを利用しています。ただし、具体的な実装はコンパイラやライブラリベンダーに依存します。

多くのC++コンパイラ(例: Microsoft Visual C++、GCC、Clang)は、Windows上で動作する際に、Win32APIをベースにしてC++標準ライブラリの実装を提供します。これにより、Windowsプラットフォーム上でC++プログラムを書く際に、標準ライブラリの機能を利用できます。

ただし、異なるプラットフォームでは異なる実装が使われることがあり、例えばLinux上では glibc などが標準ライブラリの実装として使われることがあります。したがって、クロスプラットフォームな開発を行う場合は、プラットフォームに依存しない標準ライブラリの使用を検討するか、プラットフォーム固有のコードを適切に抽象化する必要があります。

参考

std::mutex::lock

https://cpprefjp.github.io/reference/mutex/mutex/lock.html

CreateMutexW(MsDocs)

https://learn.microsoft.com/ja-jp/windows/win32/api/synchapi/nf-synchapi-createmutexw