ThreadLocal for python processes and threads

Python study notes, special records, share with you, I hope it will be helpful to everyone.

ThreadLocal

In a multithreaded environment, each thread has its own data. It is better for a thread to use its own local variables than to use global variables, because local variables can only be seen by the thread itself and will not affect other threads, and the modification of global variables must be locked.

But there are also problems with local variables, that is, it is very troublesome to pass when the function is called:

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)

How about passing the parameters of each function layer by layer? Use global variables? Nor does it work, because each thread handles different Student objects and cannot be shared.

What if you use a global dict to store all Student objects, and then use thread itself as the key to obtain the Student object corresponding to the thread?

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()]
    ...

This method is theoretically feasible, and its biggest advantage is that it eliminates the problem of passing the std object in each layer of functions, but the code for obtaining std for each function is a bit ugly.

Is there an easier way?

ThreadLocal came into being. No need to search dict, ThreadLocal will do it for you automatically:

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()

Results of the:

Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)

Process finished with exit code 0

The global variable local_school is a ThreadLocal object, and each Thread can read and write student attributes to it, but does not affect each other. You can think of local_school as a global variable, but each attribute such as local_school.student is a local variable of the thread, which can be read and written at will without interfering with each other, and there is no need to manage the lock problem, which will be handled internally by ThreadLocal.

It can be understood that the global variable local_school is a dict, not only can use local_school.student, but also bind other variables, such as local_school.teacher and so on.

The most common place for ThreadLocal is to bind a database connection, HTTP request, user identity information, etc. for each thread, so that all the processing functions called by a thread can access these resources very conveniently.

Guess you like

Origin blog.csdn.net/qq_36478920/article/details/99980041