Pythonのthreadモジュール スレッドの同期と、スレッドの使用例 スレッドの同期 Lockオブジェクト: lockオブジェクトの生成 Lockオブジェクト: lock状態の獲得 Lockオブジェクト: lock状態の開放 Lockオブジェクトの使用例: Lock_Object.py スレッドの使用例: spawn_thread.py スレッドの使用例: spawn_thread_exit.py スレッドの使用例: thread_count.py スレッドの使用例: thread_mutex.py スレッドの使用例: thread_count_wait.py Pythonのthreadモジュール スレッドの同期 スレッドを使うとき、複数のスレッドが共有する資源(グローバル変数など) にアクセスすることがあります。 このようなとき、適切にスレッドの同期を取らないと、正しく動作しないことが あります。 Pythonには、同期を取るためのオブジェクトがいくつか用意されています。 以下にPythonの同期オブジェクトを示します。 Lockオブジェクトは、最も簡便な同期機構である。Lockオブジェク トは、mutexや、binaryセマフォとも呼ばれている。 Pythonのthreadモジュール Lockオブジェクト: lockオブジェクトの生成 mtx = allocate_lock() 新しいロックオブジェクトを返します。 ロックは初期状態としてアンロック状態です。 Pythonのthreadモジュール Lockオブジェクト: lock状態の獲得 mtx.acquire([waitflag]) オプションの引数なしで使用すると、このメソッドは他のスレッドがロック しているかどうかにかかわらずロックを獲得し、None を返します。 ただし他のスレッドがすでにロックしている場合には解除されるまで待っ てからロックを獲得します (同時にロックを獲得できるスレッドはひとつだ けであり、これこそがロックの存在理由です)。 整数の引数 waitflag を指定すると、その値によって動作が変わります。 引数が 0 のときは、待たずにすぐ獲得できる場合にだけロックを獲得し ます。0 以外の値を与えると、先の例と同様、ロックの状態にかかわら ず獲得をおこないます。 なお、引数を与えた場合、ロックを獲得すると True、できなかったときに は False を返します。 Pythonのthreadモジュール Lockオブジェクト: lock状態の開放 mtx.release() ロックを解放します。 そのロックは既に獲得されたものでなければなりませ んが、同じスレッドによって獲得されたものである必要 はありません。 Pythonのthreadモジュール Lockオブジェクトの使用例 Lock_Object.py # lock object import thread, time n=0 lck = thread.allocate_lock() def fadd() : global n, lck while 1: if lck.acquire() == 0 : pass else : n += 1 lck.release() time.sleep(2) def fdec() : global n, lck while 1: if lck.acquire() == 0 : pass else : n -= 1 lck.release() time.sleep(3) thread.start_new_thread(fadd, ()) thread.start_new_thread(fdec, ()) while 1: print n time.sleep(2) Lock_Object.py Pythonのthreadモジュール スレッドの使用例: spawn_thread.py threadを次々と生成する. mutexなし. import sys, time import thread def childThread(thread_id): while 1: print ' Hello from thread', thread_id time.sleep(1) def parentThread(): thread_id = 0 while 1: thread_id += 1 print ' Creating new thread' thread.start_new(childThread, (thread_id,)) print ' Destroy new thread' if raw_input() == 'q': break print "press 'q' to quit." if __name__ == "__main__": print "Test with", sys.argv[0] parentThread() spawn_thread.py Pythonのthreadモジュール スレッドの使用例: spawn_thread_exit.py threadクラスを使うメリット: 明示的にスレッド処理を停止する exit() メソッドが提供されている threadを次々と生成する. mutexなし. import sys, time import thread def childThread(thread_id): n=0 while 1: print ' Hello from thread', thread_id, 'n', n time.sleep(3) n += 1 if n > 5: thread.exit() def parentThread(): thread_id = 0 while 1: thread_id += 1 print ' Creating new thread' thread.start_new(childThread, (thread_id,)) print ' Destroy new thread' if raw_input() == 'q': break print "press 'q' to quit." if __name__ == "__main__": print "Test with", sys.argv[0] parentThread() spawn_thread_exit.py Pythonのthreadモジュール スレッドの使用例: thread_count.py threadを生成して, 自分のidとループindexを表示する. mutexなし. mutexなしなので, あるスレッドのループが完全に終了する前に, 他スレッドのループ出力が表示される可能性がある. import sys, time import thread def childThread(my_id, count): for i in range(0, count): time.sleep(1.0) print ' [my_id = %s] => %s' % (my_id, i) def parentThread(): for my_id in range(0, 10): print 'Create new thread [my_id = %s]' % (my_id,) thread.start_new(childThread, (my_id, 3)) print 'Destroy new thread [my_id = %s]' % (my_id,) time.sleep(1.0) if __name__ == "__main__": print "Test with", sys.argv[0] parentThread() Pythonのthreadモジュール スレッドの使用例: thread_mutex.py threadを生成して, 自分のidとループindexを表示する. mutexあり. ループ開始時にmutexを取得しているので, あるスレッドのループ処理中に, 他スレッドがループ表示をすることがない. import sys import thread, time def childThread(my_id, count): mutex.acquire() for i in range(count): time.sleep(1) print ' [my_id = %s] => %s' % (my_id, i) mutex.release() def parentThread(): global mutex mutex = thread.allocate_lock() for my_id in range(10): print 'Creating new thread[my_id = %s]' % (my_id,) thread.start_new_thread(childThread, (my_id, 3)) print 'Destroy new thread[%s]' % (my_id,) time.sleep(1) if __name__ == "__main__": print "Test with", sys.argv[0] parentThread() Pythonのthreadモジュール スレッドの使用例: thread_count_wait.py counter()関数のスレッドを作る. mutexあり. stdout用のmutex. すべてのスレッドが死ぬまで, 手動でブロックする. import sys, time import thread stdout_mutex = thread.allocate_lock() exit_mutexes = [0] * 10 def childThread(my_id, count): global exit_mutexes for i in range(count): stdout_mutex.acquire() print ' [my_id = %s] => %s' % (my_id, i) stdout_mutex.release() exit_mutexes[my_id] = 1 def parentThread(): for i in range(10): print 'Create new thread [my_id = %s]' % (my_id,) thread.start_new(counter, (i, 100)) print 'Destroy new thread [my_id = %s]' % (my_id,) while 0 in exit_mutexes: pass if __name__ == "__main__": print "Test with", sys.argv[0] parentThread()
© Copyright 2024 ExpyDoc