[Python-ml-jp 3754] Re: python での co-operative multi thread programming
kenji
kenji @ nasuinfo.or.jp
2006年 10月 13日 (金) 12:37:40 JST
小林@那須です。返答ありがとうございます。
>本当にpre-emptiveかどうかは下層のスレッドライブラリに依存す
>るんじゃないでしょうか。
Python は pre emptive な thread の実装だと勝手に断定していました。付
録 1 のコードを実行してみて、 test and set の狭間でのデータ化けが発生
したことだけで pre-emptive だと判断してしまいました。でも
pre-emptive な thread は優先する thead の実行要求のために優先されない
thead の実行が中断されるものです。この意味で python は pre-emptive
な thread ではないですね。
もう少し調べ/考えてみると python での thread 実装は
・スレッドを生成するときスタック・フレームを割り当て
・Python マシン・コード 100 命令ごとにコンテキスト・スイッチ すなわち
プログラム・カウンタとスタック・フレームを切り替え
・スレッド間の調整として Lock が実装してある。Lock に失敗中のスレッド
はコンテキスト・スイッチの対象にしない
を行っているだけだと解ります。タイム・スライスに近いしろものです。
Pre-emptive/co-operative を論ずるしろものではありませんでした。優先的
な処理を thead に行わせるために thread and safe の狭間でのデータ化け
が発生しているのではありません。100 instruction slice という単純な切
り替えのために thread and safe の狭間でのデータ化け発生しただけでした。
python thread の根本的な問題は
・既存モジュールの thread safe 性について感知しない
ことでしょう。極端な例として time.sleep(.) をあげます。マルチスレッド
で CPU 時間負荷を分散するために必要な timer.sleep(.) 関数についてさえ、
python の仕様としては thread safe を保証していません。また
timer.sleep(.) 関数の中で、それを呼び出した thead の lock を解除して
くれることも期待できないでしょう。これでは python で multi thread
programming するなと言っているに等しいと思います。
>「スレッドは体に良くない。非同期にしなさい。コールバックしなさい」の
>Twisted 教に入信するといテもあるし。
と書いてくれたのが不思議でした。C プログラムでこんなことを言ったとし
たら馬鹿げています。でも上のことを考えると python でならば納得できま
す。
現状の python で thread safe を保証したいならば stackless python を使
うしかないのでしょう。
皆様の御指摘で python thread について理解を深められました。ありがとう
ございました。
================ kVerifierLab =====================
小林憲次
http://www.nasuinfo.or.jp/FreeSpace/kenji/index.htm
===================================================
----------------- 付録 ---------------------
//@@
# -*- coding: shift_jis -*-
# Thread test
import threading
import time
inGlb=0
class MyTask(threading.Thread) :
def run(self) :
#for i in range(0, 2000) : # assert エラーにならないことのほうが多い
for i in range(0, 8000) : # assert エラーになったり、ならなかったり
#for i in range(0, 20000) : # assert エラーに確実になる
global inGlb
if inGlb == 1:
inGlb -= 1
elif inGlb == 0:
inGlb += 1
else:
print "assert error:", i
assert(False)
# print i/o 命令を実行させると、そこでコンテキスト・スイッチなりエラーにならないかと思ったが
# assert エラーが発生する
print "i:", i
#time.sleep(0.01)
task1 = MyTask()
task2 = MyTask()
task1.start()
task2.start()
for n in range(20):
time.sleep(0.1)
print "main:", n
print 'end'
//@@@
//copy \#####.### temp.py /y
Python-ml-jp メーリングリストの案内