質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

646閲覧

異なるスレッドに別々にロックをかけたい

hiroshi77

総合スコア12

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2021/12/12 01:45

チームAとチームBというスレッドで、並列処理を実行していきたいのですが上手くいきません。
teamAにはtanakakun,yoshidakunというメンバーがそれぞれいて、tanakakunの処理が終了してからyoshidakunを実行したいので、tanakunの処理にロックをかけて、終了したら開放しています。
ここまでは上手くいくのですが、同時にチームBも走らせて、tigerの処理が終了してからcatの処理を走らせたいのですが、tigerの処理がチームAのtanakakunの処理が終わるまで実行されません。
チームAというスレッドにかけたロックがチームBのスレッドにも影響している状況だと判断しています。
どのように、異なるスレッドに別々のロックをかければ良いのでしょうか。

python

1import threading 2import time 3import datetime 4 5lock = threading.Lock() 6 7def time_disp(): 8 dt_now = datetime.datetime.now() 9 # 書式化した時間と生の状態2つをタプル型で返す 10 return (f"{dt_now.hour}時:{dt_now.minute}分:{dt_now.second}秒", dt_now) 11 12def teamA(take_time=1,lock=lock): 13 print(take_time) 14 lock.acquire() 15 thread_name = threading.current_thread().getName() 16 start_time,startt = time_disp() 17 print(f"僕のスレッド名は {thread_name} です") 18 print(f"{start_time}::{thread_name}行きます.") 19 time.sleep(take_time) 20 finish_time,finisht = time_disp() 21 print(f"{finish_time}::{thread_name}フィニッシュ") 22 elapsed_time = finisht - startt 23 print(f"経過時間::{elapsed_time}") 24 lock.release() 25 26def teamB(take_time=1,lock=lock): 27 print(take_time) 28 lock.acquire() 29 thread_name = threading.current_thread().getName() 30 start_time,startt = time_disp() 31 print(f"僕のスレッド名は {thread_name} です") 32 print(f"{start_time}::{thread_name}行きます.") 33 time.sleep(take_time) 34 finish_time,finisht = time_disp() 35 print(f"{finish_time}::{thread_name}フィニッシュ") 36 elapsed_time = finisht - startt 37 print(f"経過時間::{elapsed_time}") 38 lock.release() 39 40if __name__ == '__main__': 41 print('よーいどん') 42 ## スレッドの引数はargsかkwargsで渡さないといけない。スレッド名はname=~で変更できる。 43 teamA1 = threading.Thread(target=teamA,kwargs={'take_time':5,'lock':lock},name="tanakakun") 44 teamA2 = threading.Thread(target=teamA,kwargs={'take_time':3},name="yoshidakun") 45 46 teamB1 = threading.Thread(target=teamB,kwargs={'take_time':2,'lock':lock},name="tiger") 47 teamB2 = threading.Thread(target=teamB,kwargs={'take_time':9},name="cat") 48 49 teamA1.start() 50 teamB1.start() 51 52 print("match") 53 teamA2.start() 54 55 teamB2.start() 56 57 ## joinでスレッド処理が終了するのを待つ 58 59 teamA1.join 60 teamB1.join() 61 teamA2.join() 62 teamB2.join() 63 print("競争終了!!!!") 64

実行結果

よーいどん 5 僕のスレッド名は tanakakun です 10時:31分:54秒::tanakakun行きます. 2 match 3 9 10時:31分:59秒::tanakakunフィニッシュ 経過時間::0:00:05.012617 僕のスレッド名は tiger です 10時:31分:59秒::tiger行きます. 10時:32分:1秒::tigerフィニッシュ 経過時間::0:00:02.005220 僕のスレッド名は yoshidakun です 10時:32分:1秒::yoshidakun行きます. 10時:32分:4秒::yoshidakunフィニッシュ 経過時間::0:00:03.012514 僕のスレッド名は cat です 10時:32分:4秒::cat行きます. 10時:32分:13秒::catフィニッシュ 経過時間::0:00:09.011031 競争終了!!!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

最小限に近い変更だと下記のようになるでしょうか。

別々のロックを用意して異なるスレッドに各ロックを対応させます。

・チームA・Bの挙動が分かりにくかったので、出力内容を修正しています。

python

1import threading 2import time 3import datetime 4 5 6def time_disp(): 7 dt_now = datetime.datetime.now() 8 # 書式化した時間と生の状態2つをタプル型で返す 9 return (f"{dt_now.hour}時:{dt_now.minute}分:{dt_now.second}秒", dt_now) 10 11def teamA(take_time=1,lock=None): 12 # print(take_time) 13 lock.acquire() 14 thread_name = threading.current_thread().getName() 15 start_time,startt = time_disp() 16 print(f"[teamA]僕のスレッド名は {thread_name} です。") 17 print(f"[teamA]{start_time}::{thread_name}行きます.({take_time}秒後にゴール)") 18 time.sleep(take_time) 19 finish_time,finisht = time_disp() 20 print(f"[teamA]{finish_time}::{thread_name}フィニッシュ") 21 elapsed_time = finisht - startt 22 print(f"[teamA]経過時間::{elapsed_time}") 23 lock.release() 24 25def teamB(take_time=1,lock=None): 26 # print(take_time) 27 lock.acquire() 28 thread_name = threading.current_thread().getName() 29 start_time,startt = time_disp() 30 print(f"[teamB] 僕のスレッド名は {thread_name} です。") 31 print(f"[teamB] {start_time}::{thread_name}行きます.({take_time}秒後にゴール)") 32 time.sleep(take_time) 33 finish_time,finisht = time_disp() 34 print(f"[teamB] {finish_time}::{thread_name}フィニッシュ") 35 elapsed_time = finisht - startt 36 print(f"[teamB] 経過時間::{elapsed_time}") 37 lock.release() 38 39if __name__ == '__main__': 40 lockA = threading.Lock() 41 lockB = threading.Lock() 42 print('よーいどん') 43 ## スレッドの引数はargsかkwargsで渡さないといけない。スレッド名はname=~で変更できる。 44 teamA1 = threading.Thread(target=teamA,kwargs={'take_time':5,'lock':lockA},name="tanakakun") 45 teamA2 = threading.Thread(target=teamA,kwargs={'take_time':3,'lock':lockA},name="yoshidakun") 46 47 teamB1 = threading.Thread(target=teamB,kwargs={'take_time':2,'lock':lockB},name="tiger") 48 teamB2 = threading.Thread(target=teamB,kwargs={'take_time':9,'lock':lockB},name="cat") 49 50 teamA1.start() 51 teamB1.start() 52 53 print("match") 54 teamA2.start() 55 56 teamB2.start() 57 58 ## joinでスレッド処理が終了するのを待つ 59 60 teamA1.join 61 teamB1.join() 62 teamA2.join() 63 teamB2.join() 64 print("競争終了!!!!")

(threading.Eventを使用した方がもっとすっきり書けるかもしれません

投稿2021/12/12 02:07

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroshi77

2021/12/12 06:28

おかげさま様で、別々のロックを用意することで希望通りの実行できました! 出力内容の修正も助かります。 threading.Eventも調査してみたいと思います。 どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問