« IE6はHTTPS時に証明書の種類のチェックしない? | メイン | Perl関数のプロトタイプ »

Pythonのスレッドの扱い

ずいぶん前に友人とPythonのスレッドの実装の話になって
調べた時の内容が案外レアかもしれないのでメモです。
たぶんRuby1.9に実装されたYARVも大体同じような実装でしょう。

  • PythonのスレッドはOSの提供するネイティブスレッドと直接対応する
  • しかし、CPythonでは同時に動作するスレッドは1個のみ(GiantGlobal Intepreter Lock)
  • したがって遊んでいるCPUコアがあっても1個しか使われない
  • JythonやIronPythonでは複数スレッドが同時に動く
  • それぞれのPythonVMの命令が実行されている間は、Pythonスレッドが切り替わらないことが保証されている
  • スレッドの切り替えはsys.setcheckintervalで設定された値の数(デフォルト100)の命令が実行されるか、I/O待ち、Sleepに入った時に行われる
  • このためCPythonではスレッドセーフのために同期処理を入れなくても大体動くが、不幸にもスレッド切り替えをまたいだ場合はRace Conditionが発生する可能性がある
  • いままでCPythonでも同時に複数のスレッドが動くようにしてほしいという要望が何回も出ているが、拡張モジュールをスレッドセーフにすることを考えると到底無理ということで却下され続けている

ためしにPythonのスレッドを100個作ってみると、
OS上のスレッドは101個(1個はインタプリタのメインスレッド)できているのが確認できます。
Ruby1.8系だといくつスレッドを作ってもOS上のスレッドの数は変わらないのと違うところですね。

参考:
Python C/API リファレンス 8.1 スレッド状態 (thread state) とグローバルインタプリタロック (global interpreter lock)
Python 2.5.1のソースコードのWin32スレッド実装

トラックバック

このエントリーのトラックバックURL:
http://antas.jp/mtsys/mt-tb.cgi/338

コメント (2)

古いエントリに失礼:

間違いに気づいたのでいくつか指摘させていただきます。
GIL は Giant Intepreter Lock ではなく Global Interpreter Lock の略です。
GIL 無しの Python 実装のアイデアが「拡張モジュールをスレッドセーフにすることを考えると到底無理ということで却下され続けている」という事実はありません。
GIL 無しの Python を実装しても結果的に GIL 有りのものよりかなり遅くなってしまい役に立たないというのが理由です。
http://www.python.org/doc/faq/library/#can-t-we-get-rid-of-the-global-interpreter-lock

山川:

こんな古いエントリにコメントありがとうございます!

自分で挙げた参考文献にglobalってかいてありますね。良く読んでない証拠ですね…
IronPython等でGILを取り除けたのは
パフォーマンスの問題が解決できたんでしょうか。
(GCがあるとリファレンスカウンタの変更毎にロックしなくても良いのであまり影響がないとか?)

Thread関係のベンチマークを見つけましたが結構コスト大きいんですね。
http://jessenoller.com/2009/02/01/python-threads-and-the-global-interpreter-lock/

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)