C LANGUAGE TECHNOLOGY

【C言語】ミューテックスとは

悩んでいる人

C言語でミューテックスを教えて!

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOSの授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校コンピュータサイエンス学部2021年の世界大学学術ランキングで20位)で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発
  • プログラミング歴15年以上,習得している言語: C/C++Solidity,Java,Python,Ruby,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開

こういった私から学べます.

本記事ではスレッドとプロセスを理解している前提で説明します.

スレッドとプロセスを学びたいあなたはこちらからどうぞ.

C言語 スレッド
【C言語】スレッドの生成と実行【pthread,マルチスレッド,スレッドIDの取得】

こういった悩みにお答えします. こういった私から学べます. 目次1 スレッド2 pthreadによるマルチスレッドプログラミング3 pthreadでスレッドIDの取得3.1 pthread_self関 ...

続きを見る

C言語 プロセス
【C言語】プロセスの生成と実行【fork/wait/execve/getpid/getppid関数】

こういった悩みにお答えします. こういった私から学べます. 目次1 プロセス2 fork関数でプロセスの生成,wait関数で子プロセスの終了まで待機3 execve関数でコマンドの実行4 getpid ...

続きを見る

ミューテックス

ミューテックス(MUTEX:MUTual EXclusion)とは,共有資源にアクセスする際(クリティカルセクションに出入りする際),アトミックな処理を実行するための排他制御や同期機構の一つです.

ミューテックスはアンロック状態(どのスレッドやプロセスに保有されていない)とロック状態(1つのスレッドやプロセスに保有されている)の2つの状態をとります.

2つの異なるスレッドやプロセスが同時に1つのミューテックスを保有できません.

既に他のスレッドやプロセスによりロックされたミューテックスをロックしようとするスレッドやプロセスは,保有側のスレッドやプロセスが先にそのミューテックスをアンロックするまで実行を停止します.

ミューテックスとセマフォの違いは,ミューテックスはロックとアンロックの2つの状態しかとらないのに対して,セマフォは任意個の状態をとることが可能です.

セマフォを知りたいあなたはこちらからどうぞ.

C言語 セマフォ
【C言語】セマフォとは

こういった悩みにお答えします. こういった私から学べます. 本記事ではスレッドとプロセスを理解している前提で説明します. スレッドとプロセスを学びたいあなたはこちらからどうぞ. 目次1 セマフォ2 P ...

続きを見る

LinuxにはPOSIXのミューテックス「POSIXミューテックス」が実装されていますので,本記事ではPOSIXミューテックスの使い方を解説していきます.

POSIXミューテックス

pthread_mutexは,POSIXのミューテックスです.

pthread_mutex_init関数は第1引数のmutexが指すミューテックスオブジェクトを,第2引数mutexattrで指定されたミューテックス属性オブジェクトに従って初期化します.

mutexattrがNULLの場合,デフォルトの属性が利用されます.

pthread_mutex_lock関数は,第1引数のmutexをロックします.

mutexが現在ロックされていなければ,それはロックされ,呼び出しスレッドにより所有されます.

この場合,pthread_mutex_lock関数は直ちに返ります.

mutexが他のスレッドによって既にロックされていた場合,pthread_mutex_lock関数はmutexがアンロックされるまで呼び出しスレッドの実行を停止させます.

pthread_mutex_trylock関数はpthread_mutex_lock関数と同様の振る舞いをしますが,第1引数のmutexが既に他のスレッドによりロックされている場合,呼び出しスレッドをブロックしません.

その代わり,pthread_mutex_trylock関数はエラーコードEBUSYで直ちに戻ります.

pthread_mutex_unlock関数は,第1引数mutexをアンロックします.

pthread_mutex_destroy関数は,第1引数mutexオブジェクトを破壊し,それが保持している可能性のある資源を解放します.

pthread_mutexattr_init関数は,第1引数のmutex属性オブジェクトattrを初期化し,すべての属性をデフォルトの値に設定します.

pthread_mutexattr_setpshared関数は,第2引数psharedで指し示される領域にPTHREAD_PROCESS_PRIVATEを格納し,常に0を返します.

POSIXミューテックスをスレッド間で利用

スレッド間のロックにpthread_mutex_lock関数を利用

スレッド間のロックにpthread_mutex_lock関数を利用するコードは以下になります.

実行結果は以下になります.

countの数値がLOOP_NUM(=50000)の2倍,つまり50000 * 2 = 100000になることがわかります.

-DNO_LOCKオプションを付けてコンパイルした場合の実行結果は以下になります.

5行目の「count = 75048」で100000より小さい値になっていることがわかります.(100000や他の値になる場合もあります.)

この理由は,Linuxはプリエンプティブ・マルチタスクの実行が可能なため,countのインクリメント処理でインターリーブが発生してしまうからです.

スレッド間のロックにpthread_mutex_trylock関数を利用

スレッド間のロックにpthread_mutex_trylock関数を利用するコードは以下になります.

実行結果は以下になります.同様です.

-DNO_LOCKオプションを付けてコンパイルした場合の実行結果は以下になります.同様です.

POSIXミューテックスをプロセス間で利用

POSIXミューテックスをプロセス間で利用するコードを紹介します.

結構難しいので読み飛ばしても構いませんが,理解したいあなたは是非挑戦しましょう!

プロセス間のロックにpthread_mutex_lock関数を利用

プロセス間のロックにpthread_mutex_lock関数を利用するコードは以下になります.

shm_open/shm_unlink関数でプロセス間の共有メモリの作成と削除を行っています.

実行結果は以下になります.

shm_open/shm_unlink関数を利用する際は-lrtオプションが必要なことに注意して下さい.

6行目の「*count = 100000」で正常にカウントできていることがわかります.

※5行目の*countは先に実行終了した親プロセスまたは子プロセスの表示です.

-DNO_LOCKオプションを付けてコンパイルした場合の実行結果は以下になります.

6行目の「*count = 85108」で100000より小さい値になっていることがわかります.

プロセス間のロックにpthread_mutex_trylock関数を利用

プロセス間のロックにpthread_mutex_trylock関数を利用するコードは以下になります.

実行結果は以下になります.同様です.

-DNO_LOCKオプションを付けてコンパイルした場合の実行結果は以下になります.同様です.

まとめ

C言語でミューテックスを紹介しました.

具体的には,ミューテックスでスレッドやプロセス間でデータをアトミックに操作する方法を解説しました.

ミューテックスを利用しないとインクリメント処理が正常に実行されないことを確認しましょう.

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

友だち追加

独学が難しいあなたは,C言語を学べるおすすめのオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , , , , , ,