2013-04-27 4 views
8

私は一般的に、PythonのGlobal Interpreter Lock(GIL)がどのように動作するかをよく理解しています。本質的に、インタープリタが実行されている間、一方のスレッドはGILをNティック(Nsys.setcheckintervalを使用して設定できます)を保持します。この時点でGILは解放され、別のスレッドはGILを取得できます。 1つのスレッドがI/O操作を開始した場合も同様です。Python:GIL context-switching

私が少し混乱しているのは、これがC拡張モジュールでどのように動作するかです。

GILを取得し、PyEval_EvalCodeを使用していくつかのPythonコードを実行するC拡張モジュールをお持ちの場合、インタープリタはGILをリリースして他のスレッドに渡すことができますか?または、GILを取得したCスレッドは、PyEval_EvalCodeが返され、GILがC言語で明示的にリリースされるまでGILを永続的に保持しますか?

PyGILState gstate = PyGILState_Ensure(); 

.... 

/* Can calling PyEval_EvalCode release the GIL and let another thread acquire it?? */ 
PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict); 

PyGILState_Release(gstate); 

答えて

2

はい、インタープリタは常にGILをリリースできます。十分な命令を解釈した後に他のスレッドに渡すか、または何らかのI/Oを行うと自動的にスレッドに渡します。最近のPython 3.x以降、基準は実行された命令の数に基づくものではなく、十分な時間が経過したかどうかに注意してください。

異なる効果を得るには、明示的にリリースするまでGILを解放しないように頼んで、GILを「アトミック」モードで取得する方法が必要です。これはこれまで不可能ですが(実験版ではhttps://bitbucket.org/arigo/cpython-withatomicを参照してください)。

+0

[関連する質問](http://stackoverflow.com/questions/29317120/forcing-a-thread-to-block-all-other-threads-from-executing)を参照してください。私はあなたのステートメントとPython Cookbookのステートメントとの間の見た目の不一致を解決する方法を理解していません。 – max

+0

[アルバートの答え](http://stackoverflow.com/a/29328066)を参照してください。 –

1

Arminが述べたように、GILはPyEval_EvalCodeの中に放出することができます。それが戻ってくると、もちろんそれは再び取得されます。

最も良い方法は、コードがそれを処理できることを確認することです。たとえば、GILがリリースされる前にCポインタを持つオブジェクトをすべてインクリメントします。また、Pythonコードが再び同じ機能を呼び出すことがある場合は注意してください。そこに別のミューテックスがあれば、簡単にデッドロックになる可能性があります。再帰的に安全なmutexを使い、それらを待っている間に元のスレッドがそのようなmutexを解放できるようにGILを解放する必要があります。