本节内容:
- 进程与线程区别
- 线程
- a) 语法
- b) join
- c) 线程锁之LockRlock信号量
- d) 将线程变为守护进程
- e) Event事件
- f) queue队列
- g) 生产者消费者模型
3. python GIL全局解释器锁
1. 进程与线程区别
线程:是操作系统能够进行运算和调度的最小单位,是一堆指令的集合。线程被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程就是cpu执行时所需要的一堆上下文关系。
进程:以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等,对各种资源管理的集合就可称为 进程。进程要操作cpu, 必须先创建一个线程。
进程和线程的区别:
- 线程共享内存空间,进程的内存是独立的
- 线程共用数据,进程数据独立
- 同一个进程的线程之间可以直接交流,两个进程必须通过中间代理实现通信
- 新线程容易创建,新进程需要克隆父进程
- 一个线程可以控制和操作同一进程里的其他线程, 进程只能操作子进程
修改主线程有可能影响到其他线程的行为,对父进程修改不会影响子进程。
2. 线程(threading模块)
a) 语法
先写一个简单的线程:
import threading import time def run(n): print("task" ,n) time.sleep(2) t1 = threading.Thread(target=run, args=("t1",)) t2 = threading.Thread(target=run, args=("t2",)) t1.start() t2.start() print(t1.getName) #获取线程名 print(t2.getName)
继承式调用:
import threading import time class MyThread(threading.Thread): def __init__(self, num): threading.Thread.__init__(self) self.num = num def run(self): # 定义每个线程要运行的函数 print("running on number:%s" % self.num) time.sleep(3) if __name__ == '__main__': t1 = MyThread(1) t2 = MyThread(2) t1.start() t2.start()
启动多个线程:
import threading import time def run(n): print("task" ,n) time.sleep(2) for i in range(50): t = threading.Thread(target=run, args=("t_%s" % i,)) t.start()
b) join
join & Daemon用法:
默认情况主线程不会等子线程执行完毕,但是join可以做到
import threading import time def run(n): print("task" ,n) time.sleep(2) print("task done ", n) start_time = time.time() t_objs = [] for i in range(50): t = threading.Thread(target=run, args=("t_%s" % i,)) t.start() t_objs.append(t) for t in t_objs: t.join() print("cost_time:",time.time()-start_time)
主线程是程序本身
threading.current_thread()和threading.active_count()用法:
import threading import time def run(n): print("task" ,n) time.sleep(2) print("task done ", n,threading.current_thread()) start_time = time.time() t_objs = [] for i in range(50): t = threading.Thread(target=run, args=("t_%s" % i,)) t.start() t_objs.append(t) # for t in t_objs: # t.join() print("===all threads has finished", threading.current_thread(), threading.active_count()) print("cost_time:",time.time()-start_time)
c) 信号量:
threading.BoundedSemaphore(n)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 。
d) 把子线程变成守护线程setDaemod()方法:
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: zhoujunlong import threading import time def run(n): print("task" ,n) time.sleep(2) print("task done ", n,threading.current_thread()) start_time = time.time() for i in range(50): t = threading.Thread(target=run, args=("t_%s" % i,)) t.setDaemon(True) # 把当前线程设置为守护线程 , 在start之前 t.start() print("===all threads has finished", threading.current_thread(), threading.active_count()) print("cost_time:",time.time()-start_time)
e) 事件:
事件是一个简单地同步对象
event = threading.event()
event.wait() 等待标志位被设定
event.set() 设置标志位
event.clear() 清除标志位
event.is_set() 判断标志位是否设定
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: zhoujunlong import threading import time event = threading.Event() def lighter(): count = 0 event.set() while True: if 10>=count > 5:#change_to_red_light event.clear() # 清空标志位 print("