##进程就像加工厂,线程是里边的流水线
##进程是资源单位,线程是运行单位,每个进程至少有一个线程
即进程是资源分配的最小单位,线程是CPU调度的最小单位
一、线程的创建
两种方式,和进程类似
1、t = Thread(target = fun,arges = (,))
2、自定义类 继承Thread,重写run方法
1 import time 2 from threading import Thread 3 class Sayhi(Thread): 4 def __init__(self,name): 5 super().__init__() 6 self.name=name 7 def run(self): 8 time.sleep(2) 9 print('%s say hello' % self.name) 10 11 12 if __name__ == '__main__': 13 t = Sayhi('太白') 14 t.start() 15 print('主线程')
#常用方法
t.join() 等待线程结束
t.isAlive() 判断进程是否还活着
current_thread().getName() 获取线程名
current_thread().ident() 获取线程id
threading.currentThread() 返回当前线程量
threading.enumerate() 返回正在运行的线程列表
二、数据共享
同一进程中线程之间是数据共享的,这就会有数据安全问题,所以需要加锁
三、死锁
双方等待对方释放锁,所以都不能执行
解决死锁方案:用递归锁RLock
递归锁里有一个计数器,只有计数器为0时,别人才能抢。当有人抢到时就计数器+1,释放时计数器-1
import time from threading import Thread, Lock, RLock def func1(lock_A, lock_B): with lock_A: # lock_A.acquire() time.sleep(0.1) print('alex拿到了A锁') # lock_B.acquire() with lock_B: print('alex拿到了B锁') # lock_B.release() # lock_A.release() def func2(lock_A, lock_B): with lock_B: # lock_B.acquire() print('taibai拿到了B锁') # lock_A.acquire() with lock_A: print('taibai 拿到了A锁') # lock_A.release() # lock_B.release() if __name__ == '__main__': lock_A = Lock() lock_B = Lock() lock_B = lock_A # lock_A = RLock() # lock_B = RLock() lock_A =lock_B =RLock() t1 = Thread(target=func1, args=(lock_A, lock_B)) t2 = Thread(target=func2, args=(lock_A, lock_B)) t1.start() t2.start()
四、守护线程
正常情况下,主线程代码结束后会等待子线程结束,子线程都结束了主线程才会结束。但是,将子线程设为守护线程后,主线程就不再等他结束,所以守护线程随着主线程的结束而结束。
#注意和守护进程的区别
守护进程时随着主进程的代码结束而结束,主进程代码结束不意味着主进程的结束,(主进程代码结束后会等着子进程结束,给他们收尸)