Pythonの研究ノート、特別な記録、あなたと共有してください、私はそれが皆に役立つことを願っています。
ThreadLocal
マルチスレッド環境では、各スレッドに独自のデータがあります。ローカル変数はスレッド自体だけが見ることができ、他のスレッドには影響を与えず、グローバル変数の変更をロックする必要があるため、スレッドはグローバル変数を使用するよりも独自のローカル変数を使用する方が適切です。
ただし、ローカル変数にも問題があります。つまり、関数が呼び出されたときに渡すのは非常に面倒です。
def process_student(name):
std = Student(name)
# std是局部变量,但是每个函数都要用它,因此必须传进去:
do_task_1(std)
do_task_2(std)
def do_task_1(std):
do_subtask_1(std)
do_subtask_2(std)
def do_task_2(std):
do_subtask_2(std)
do_subtask_2(std)
各関数のパラメーターをレイヤーごとに渡すのはどうですか?グローバル変数を使用しますか?また、各スレッドは異なるStudentオブジェクトを処理し、共有できないため、機能しません。
グローバルdictを使用してすべてのStudentオブジェクトを格納し、スレッド自体をキーとして使用して、スレッドに対応するStudentオブジェクトを取得するとどうなりますか?
global_dict = {}
def std_thread(name):
std = Student(name)
# 把std放到全局变量global_dict中:
global_dict[threading.current_thread()] = std
do_task_1()
do_task_2()
def do_task_1():
# 不传入std,而是根据当前线程查找:
std = global_dict[threading.current_thread()]
...
def do_task_2():
# 任何函数都可以查找出当前线程的std变量:
std = global_dict[threading.current_thread()]
...
この方法は理論的には実行可能であり、その最大の利点は、関数の各レイヤーでstdオブジェクトを渡す問題がなくなることですが、各関数のstdを取得するためのコードは少し見苦しいです。
もっと簡単な方法はありますか?
ThreadLocalが誕生しました。dictを検索する必要はありません。ThreadLocalが自動的に検索します。
import threading
# 创建全局ThreadLocal对象:
local_school = threading.local()
def process_student():
std = local_school.student
print 'Hello, %s (in %s)' % (std, threading.current_thread().name)
def process_thread(name):
local_school.student = name
process_student()
t1 = threading.Thread(target=process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
結果:
Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)
Process finished with exit code 0
グローバル変数local_schoolはThreadLocalオブジェクトであり、各スレッドはそれに学生属性を読み書きできますが、相互に影響を与えることはありません。local_schoolはグローバル変数と考えることができますが、local_school.studentなどの各属性はスレッドのローカル変数であり、相互に干渉することなく自由に読み書きでき、ロックの問題を管理する必要はありません。 、これはThreadLocalによって内部的に処理されます。
グローバル変数local_schoolはdictであり、local_school.studentを使用できるだけでなく、local_school.teacherなどの他の変数をバインドすることもできます。
ThreadLocalの最も一般的な場所は、各スレッドのデータベース接続、HTTP要求、ユーザーID情報などをバインドすることです。これにより、スレッドによって呼び出されるすべての処理関数がこれらのリソースに非常に便利にアクセスできます。