Python--线程
进程与线程的区别:
1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
4. 调度和切换:线程上下文切换比进程上下文切换要快得多。
多线程:
多线程工作实例1:实现类似并发执行的效果,实际上并非并发,是多个线程间进行上下文的切换
1 import threading 2 import time 3 def run(n): 4 print("task ",n ) 5 time.sleep(2) 6 print("task done",n) 7 start_time = time.time() 8 t_objs = [] #存线程实例 9 for i in range(50): 10 t = threading.Thread(target=run,args=("t-%s" %i ,)) # 实例化一个线程,指定线程执行run函数,args传参数 11 t.start() # 启动实例化的线程 12 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 13 for t in t_objs: #循环线程实例列表 14 t.join() # .join:等待线程执行完毕 15 print("----------all threads has finished...") 16 print("cost:",time.time() - start_time)
程序中,启动了50个线程,每个线程在执行run方法时,均sleep两秒,在程序结束时,实际上总体时间仅仅用了2秒多。
守护线程:设置子线程为守护线程时,当主线程结束时,子线程即结束,不会等待子线程执行完毕
守护线程实例:
1 import threading,time # 导入模块 2 3 def run(n): # 定义线程执行的函数 4 print("is task:", n, threading.current_thread()) 5 time.sleep(2) 6 print("task done",n, threading.current_thread()) 7 8 start_time = time.time() # 标记开始时间 9 10 for i in range(20): # 启动20个线程 11 t = threading.Thread(target=run, args=("t-%s" % i,)) 12 t.setDaemon(True) # .setDaemon设置线程为守护线程 13 t.start() # 启动线程 14 15 time.sleep(1) # 主线程sleep,程序执行时间完全取决于此sleep时间,与子线程的sleep无关 16 print("------threading runing done",threading.current_thread(),threading.active_count()) 17 print("cost:",time.time()- start_time) # 计算程序结束时间
程序中,以守护线程的形式启动20个子线程,在主线程结束时子线程同时结束,即使子线程尚未执行完毕。程序总花费时间为1s多。
线程锁:
由于多线程是同时执行的,多线程在修改同一个数据时,会出现修改后的数据不正确的情况。可以使用线程锁实现线程串行修改数据。
1 import threading,time # 导入模块 2 3 def run(): # 线程执行函数 4 lock.acquire() # 加锁 5 global num # 将num设置为全局变量 6 num += 1 7 print(num) 8 time.sleep(1) 9 lock.release() # 解锁 10 11 num = 0 12 t_obj = [] # 线程列表 13 lock = threading.Lock() # 实例化一个线程锁 14 for i in range(50): 15 t = threading.Thread(target=run) # 实例化一个线程 16 t.start() # 启动线程 17 t_obj.append(t) # 将线程加入线程列表 18 19 for j in t_obj: # 循环线程列表 20 j.join() 21 22 print("----------all threads has finished...",threading.current_thread(),threading.active_count()) 23 print("num:",num)
递归锁:
Rlock 递归锁,它相当于一个字典,记录了锁的门与锁的对应值,当开门的时候会根据对应来开锁.
1 import threading # 导入模块 2 3 def run1(): 4 lock.acquire() # 加锁 5 global num1 6 num1 += 1 7 lock.release() # 解锁 8 return num1 9 10 def run2(): 11 lock.acquire() # 加锁 12 global num2 13 num2 += 1 14 lock.release() # 解锁 15 return num2 16 17 def run3(): 18 lock.acquire() # 加锁 19 res = run1() # run1函数中也有锁操作 20 print("run1:",res) 21 res2 = run2() # run2函数中也有锁操作 22 print("run2:",res2) 23 lock.release() # 解锁 24 25 lock = threading.RLock() # 实例化锁 26 num1 = 0 27 num2 = 0 28 t_obj = [] # 线程列表 29 for i in range(10): 30 t = threading.Thread(target=run3) 31 t.start() 32 t_obj.append(t) 33 while threading.active_count() != 1: 34 # print(threading.active_count()) # 打印当前运行的线程数 35 pass 36 else: 37 print("num1:%s, num2:%s" % (num1, num2))
信号量
1 import threading,time 2 3 def run(n): 4 semaphore.acquire() # 加锁 5 time.sleep(1) 6 print("in run:",n) 7 semaphore.release() # 解锁 8 9 semaphore = threading.BoundedSemaphore(3) # 加锁的情况下,允许3个线程同时执行,不必等线程解锁后下个线程才工作,3线程并发 10 for i in range(20): 11 t = threading.Thread(target=run,args=(i,)) 12 t.start()