线程,进程
定义:
进程: 是对各种资源管理的集合,qq 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等
线程: 是操作系统最小的调度单位, 是一串指令的集合。
进程要想操作CPU,就必须要创建一个线程(进程中至少包含一个线程)
区别:
1.线程共享内存空间(共享数据等),进程的内存空间是独立的
2.同一进程的线程之间可以相互交流 ,2个进程之间的交流必须通过一个中间代理
3.线程可以操作和控制其他线程(同一进程下),进程只能操作和控制子进程。
对主线程的更改可能会影响到其他线程的工作,对父进程的更改(除非关闭)不会影响子进程。(子进程还可以派生子进程)
Python中的多线程
import threading def run(n): print('运行线程',n) for i in range(10): # 创建10个线程 t = threading.Thread(target=run, args=(i,)) # 线程运行的函数和参数 t.setDaemon(True) # 设置为守护线程(在主线程线程结束后自动退出,默认为False即主线程线程结束后子线程仍在执行) t.start() # 启动线程
上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。
更多方法:
- start 线程准备就绪,等待CPU调度
- setName 为线程设置名称
- getName 获取线程名称
- setDaemon 设置为后台线程或前台线程(默认)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 - join 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
- run 线程被cpu调度后自动执行线程对象的run方法
互斥锁(Lock、RLock)
由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。
import threading import time gl_num = 0 lock = threading.RLock() # 定义线程锁 def Func(): lock.acquire() # 开始锁 global gl_num gl_num += 1 time.sleep(1) print(gl_num) lock.release() # 结束锁 for i in range(10): t = threading.Thread(target=Func) t.start() """ 没有锁的时候打印: >> 10,10,10,10,10,10,10,10,10,10 有锁的时候打印: >> 1,2,3,4,5,6,7,8,9,10 """
信号量(Semaphore)
互斥锁同时只允许一个线程更改数据,而信号量锁是同时允许一定数量的线程更改数据 ,多个线程同时执行完毕。
import threading, time def run(n): semaphore.acquire() # 信号量锁开始 time.sleep(1) print("当前运行线程为: %s" % n) semaphore.release() # 结束 if __name__ == '__main__': num = 0 semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行(5个5个一起出来) for i in range(20): t = threading.Thread(target=run, args=(i,)) t.start()
事件(event)
python线程的事件用于主线程控制其他线程的执行,事件主要提供了两个方法:event.set()设定,event.clear()没设定。
- event.wait():等待设定
- event.is_set():判断是否设定
1 import time,threading 2 3 event = threading.Event() 4 5 def lighter(): 6 count=0 7 event.set() #设定 8 while True: 9 if count<10 and count>=5: 10 event.clear() #清除设定 11 print("