Pythonスレッドローカルとグローバルロックの特徴
多スレッドプログラミングでデータの一貫性を維持し、競合状態を防ぐために重要なツールであるスレッドロックとグローバルロック。
Pythonのthreading.Lockは再入可能なロックであり、同じスレッドが一度ロックを獲得した後、ロックを再度獲得してもデッドロックが発生しないことが特徴です。
- ロックを取得できるスレッドは1つのみで、それ以外のスレッドはロックが解放されるまで待つ必要がある。
- スレッドがロックを獲得している場合、他のスレッドがロックを要求すると、ロックが解放されるまでブロックされます。
- スレッドロックはフェアではなく、ロックを待っている時間が一番長いスレッドが優先的にロックを取得できることを保証しません。
- スレッドロックは複数のスレッド間で共有でき、つまり複数のスレッドが同一のロックオブジェクトを使用して同期できます。
グローバルロックとは、Pythonインタプリタに存在するグローバルインタプリタロック(GIL)のことで、以下のような特徴を持っています。
- GILとは、Pythonインタプリタのメカニズムのことで、Pythonバイトコードを一度に1つのスレッドのみで実行するようにしています。
- GILのせいでマルチスレッドプログラム内の複数のスレッドは本当の意味での並列実行ができず、シングルコアCPU上では単にタイムスライスで切り替わっているだけ
- GILはマルチスレッドプログラムの競合状態(race condition)を防ぐ役割があるが、Pythonのマルチスレッドプログラムのパフォーマンスを制限する要因にもなっている。
要約すると、スレッドロックとは、共有リソースを保護するために使用される仕組みで、グローバルロックとは、インタプリタレベルの同期を制御するために使用される仕組みです。スレッドロックは複数スレッド間で共有可能ですが、グローバルロックはPythonインタプリタレベルです。