其他关于Python的总结文章请访问:https://www.jianshu.com/nb/47435944
详解Python中的多线程、线程锁、线程变量 – threading、Thread、Lock与ThreadLocal详解
关于多进程的内容请参考:<>
一个进程可以包含多个线程,而且至少必须要有一个线程,这个线程被称为主线程,在Python中的名字为 MainThread。进程与线程最大的不同在于,进程的信息时各自的,而(同一个进程下的)线程的信息是公用的,即他们都处理、使用所在进程的信息数据等。
可以使用Python中的threading模块进行线程管理于操作。使用 threading.current_thread() 获取当前所在线程,使用线程实例的name属性获取线程的名字。
使用Thread创建多线程
一个python运行起来后对应着一个进程,这个进程的的主线程即 MainThread,使用Thread可以创建新的线程,创建时使用参数 target 绑定线程运行的目标,使用 name 参数为线程定义一个名字。
Thread的实例有的常用方法:
-
start:开始执行这个线程 -
join:等待线程执行结束
一个例子:
import time, random, threading
def print_time():
time.sleep(random.random())
print("I m thread {}, time now is {}".format(threading.current_thread().name, time.time()))
print("The main thread is {}".format(threading.current_thread().name))
thread1 = threading.Thread(target=print_time, name="New Thread 1")
thread2 = threading.Thread(target=print_time, name="New Thread 2")
thread3 = threading.Thread(target=print_time, name="New Thread 3")
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
得到的结果是随机的:
The main thread is MainThread
I m thread New Thread 3, time now is 1607256751.4239407
I m thread New Thread 1, time now is 1607256751.8748183
I m thread New Thread 2, time now is 1607256751.9063895
使用锁Lock修改数据
由于(同一个进程下的)多个线程使用的是同一套数据,所以如果多个线程同时访问一个数据就会造成冲突,解决的方法是使用线程锁,在某个线程修改这个数据的时候,它获得一把锁,只有获得锁的这个线程有权利修改这个数据,等修改完成后再释放锁,这样就可以保证在一个时间只有一个线程修改这个数据。如果多个线程都想请求得到锁,他们会排队获得。
Python中使用threading.Lock来完成,一个Lock实例常用的的方法有:
-
acquire:请求获得锁 -
relaese:释放锁
为例确保一个线程在使用完后必定会释放锁,一般使用try...final...语句,将释放锁的代码放在finally块里。
一个例子:一个线程要给一个数据加一,一个线程要给同一个数据减一:
import time, random, threading
number = 0
lock = threading.Lock()
def add_one():
global number
for i in range(20):
lock.acquire()
print("I m thread {}, I acquired the lock.".format(threading.current_thread().name))
try:
number += 1
finally:
lock.release()
print("I m thread {}, I realised the lock.".format(threading.current_thread().name))
def minus_one():
global number
for i in range(20):
lock.acquire()
print("I m thread {}, I acquired the lock.".format(threading.current_thread().name))
try:
number -= 1
finally:
lock.release()
print("I m thread {}, I realised the lock.".format(threading.current_thread().name))
thread_add = threading.Thread(target=add_one, name="Thread ADD")
thread_minus = threading.Thread(target=minus_one, name="Thread MINUS")
thread_add.start()
thread_minus.start()
thread_add.join()
thread_minus.join()
使用ThreadLocal创建进程局部变量
设想如果有多个线程,它们都要处理自己的一个变量,但是又想进行对于该变量的信息交换,这样的情况下,可以使用一个全局变量来记录每个线程的局部变量(列如一个字典),显然是很麻烦的,于是可以使用ThreadLocal来处理线程的局部变量。
一个例子:两个线程都有各自的变量number
import threading
local_variable = threading.local()
def print_number():
number = local_variable.number
print("I m thread {}, I m processing my number {}".format(threading.current_thread().name, number))
def set_number(num):
local_variable.number = num
print_number()
thread1 = threading.Thread(target=set_number, args=(1,), name="Thread 1")
thread2 = threading.Thread(target=set_number, args=(2,), name="Thread 2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
得到的结果如下:
I m thread Thread 1, I m processing my number 1
I m thread Thread 2, I m processing my number 2