こんにちは😀
今回は、前回の続きでタスク排他と同期制御に関してみていきます。
前回は主にタスクの排他制御をまとめました。
デッドロックとは
排他制御において、複数のリソースをそれぞれのタスクが無秩序にロックしていくことで、互いに他のタスクがロックしているリソースの解除待ちに入ってしまうことがあります。
この状態になると、処理が進行しなくなるという現象が起こる可能性があります。
この状態をデッドロックと言います。
具体例を以下に表にしてみます。
タスクA | リソース1 | リソース2 | タスクB |
リソース1をP操作 | リソース2をP操作 | ||
↓ | タスクAによりロック | タスクBによりロック | ↓ |
リソース2をP操作 | (ロック中) | (ロック中) | リソース1をP操作 |
ロックできずにリソース2の解除待ち | (ロック中) | (ロック中) | ロックできずにリソース1の解除待ち |
↓ | (ロック中) | (ロック中) | ↓ |
これがデッドロックの状態で、お互いが延々と相手のロックしている資源を待ち続けてしまいます。
デッドロックを避けるためには、リソースのロック順序を両方のタスクで同じに揃える必要があります。
順序が同じであれば、リソースの解除に応じて次のタスクがロックできるようになるので、デッドロックの問題は生じません。
同期処理とは
複数のタスクがお互いに依存関係をもち、一方の処理を待って他方が処理の実行を再開するといった協調動作も行われます。
このようなタスク同士を協調させるために、それぞれの実行タイミングを図る仕組みを、同期制御と言います。
タスク間の同期方法として、もっとも基本的な手法にイベントフラグがあります。
イベントフラグは、カーネルの監視下に置かれたビットの集合であり、1つのビットが1つのイベントを表すフラグになっています。
イベントフラグは、複数タスクの待機状態を同時に解除させる他にも、複数の条件が整ったときに待機を解除させるなど、様々な指定を行うことが可能です。
タスク間の通信に関して
タスク同士が協調して動作をする際に、その間でデータのやり取りをしながら処理を進める場合は、通信手段が必要になります。
タスク間の通信に用いられる代表的な手法として以下のものがあります。
共有メモリ
メモリ上に複数のタスクから利用できる記憶領域を設けてデータ交換を行います。
メッセージキュー
メッセージ処理用のキュー(待ち行列)にタスクからのデータをメッセージとして送信し、受信側でこのキューを介してデータを受け取ります。
パイプ
仮想的なパイプを通してデータをやり取りする仕組みです。
あるタスクの出力を、もう一方のタスクに接続し、データを転送します 。
今回の一言・・・
前回に続き、デッドロックを回避して同期制御をうまくできるよう設計できるのが大事になります。
ここまで読んでくれてありがとう。
では、また次回。