一、使用threading模块实现多线程
import threading import time def test(): print('111111111') if __name__ == '__main__': for i in range(5): t = threading.Thread(target=test) t.start() #启动线程
二、使用threading子类实现多线程
import threading import time class myThread(threading.Thread): def run(self): for i in range(3) time.sleep(1) print(11111) if __name__ == '__main__': t = myThread() t.start()
三、一些注意点
1.多线程之间共享全局变量
from threading import Thread import time def work1(nums): nums.append(44) print(num1) def work2(num2): time.sleep(1) print(num2) g_nums = [11, 22, 33] t1 = Thread(target=work1, args=(g_nums,)) t1.start() t2 = Thread(target=work2, args=(g_nums,)) t2.start()
四、互斥锁
在多个线程操纵一个全局变量时,可能会出现同时执行的情况,这样对全局变量的值得修改会同步发生,有可能引起全局变量数据的重复作业,使最终的结果比应当得到的结果少。解决这个问题可用用两个方法,一个是用轮询的方式,一个线程先执行,另一个线程不断轮询,等上一个线程执行完毕后,得到一个开始执行的信号,然后开始执行,第二种方式就是使用互斥锁
from threading import Thread,Lock #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([true|false, timeout]) #true:当前线程会堵塞,默认 #false:不会堵塞 #释放 mutex.release()
五、死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
1.避免死锁的方法:
(1)添加超时时间。
六、同步
from threading import Thread,Lock from time import sleep class Task1(Thread): def run(self): while True: if lock1.acquire(): print("------Task 1 -----") sleep(0.5) lock2.release() class Task2(Thread): def run(self): while True: if lock2.acquire(): print("------Task 2 -----") sleep(0.5) lock3.release() class Task3(Thread): def run(self): while True: if lock3.acquire(): print("------Task 3 -----") sleep(0.5) lock1.release() #使用Lock创建出的锁默认没有“锁上” lock1 = Lock() #创建另外一把锁,并且“锁上” lock2 = Lock() lock2.acquire() #创建另外一把锁,并且“锁上” lock3 = Lock() lock3.acquire() t1 = Task1() t2 = Task2() t3 = Task3() t1.start() t2.start() t3.start() #结果 ------Task 1 ----- ------Task 2 ----- ------Task 3 ----- ------Task 1 ----- ------Task 2 ----- ------Task 3 ----- ------Task 1 ----- ------Task 2 ----- ------Task 3 ----- ------Task 1 ----- ------Task 2 ----- ------Task 3 ----- ------Task 1 ----- ------Task 2 ----- ------Task 3 -----
七、线程中的队列
from Queue import Queue(python2)
from queue import Queue(python3)用法与进程中的queue用法相同
八、ThreadLocal
全局变量local_school就是一个ThreadLocal对象,每个Thread对它都可以读写student属性,但互不影响。你可以把local_school看成全局变量,但每个属性如local_school.student都是线程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。
import threading # 创建全局ThreadLocal对象: local_school = threading.local() def process_student(): # 获取当前线程关联的student: std = local_school.student print('Hello, %s (in %s)' % (std, threading.current_thread().name)) def process_thread(name): # 绑定ThreadLocal的student: local_school.student = name process_student() t1 = threading.Thread(target= process_thread, args=('dongGe',), name='Thread-A') t2 = threading.Thread(target= process_thread, args=('老王',), name='Thread-B') t1.start() t2.start() t1.join() t2.join() #结果: Hello, dongGe (in Thread-A) Hello, 老王 (in Thread-B)