Python多线程,多进程
---恢复内容开始---
ssh 密钥
RSA-非对称密钥验证
公钥 public key
私钥 private k
10.0.0.31 ---->10.0.0.41
私钥 公钥
自己拿着私钥,把公钥给别人,成对出现,这样就可以双方通信了
进程和线程
线程:一堆指令,是操作系统最小的调度单位,是一串指令的集合,它被包含在进程之中
进程:qq要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用。。。
对各种资源管理的集合就可以称为进程
所有在同一个进程里的线程是共享同一块内存空间
进程和线程一样快,没有可比性,但是启动一个线程快,因为就是一堆指令,一运行之后,都是一样的,因为进程通过线程
全局解释器锁
Python GIL(Global Interpreter Lock)
无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行。
但是GIL并不是Python的特性,Python完全可以不依赖于GIL
线程的调用模式
1 import threading 2 import time 3 4 def sayhi(num): # 定义每个线程要运行的函数 5 print("running on number:%s" % num) 6 time.sleep(3) 7 8 if __name__ == '__main__': 9 t1 = threading.Thread(target=sayhi, args=(1,)) # 生成一个线程实例 10 t2 = threading.Thread(target=sayhi, args=(2,)) # 生成另一个线程实例 11 12 t1.start() # 启动线程 13 t2.start() # 启动另一个线程 14 15 print(t1.getName()) # 获取线程名 16 print(t2.getName())
基本上用的都是这个调用方式,还有一种继承式调用,不实用
守护线程
1 import time 2 import threading 3 4 def run(n): 5 print('[%s]------running----\n' % n) 6 time.sleep(2) 7 print('--done--') 8 9 def main():#main线程 10 for i in range(5): 11 t = threading.Thread(target=run, args=[i, ]) 12 t.start() 13 t.join(1) 14 print('starting thread', t.getName()) 15 16 m = threading.Thread(target=main, args=[]) 17 m.setDaemon(True) #将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务 18 m.start() 19 m.join(timeout=2) 20 print("---main thread done----")
LOCK
线程在同事修改同一份数据的时候必须加锁
join() 等一个线程的执行结果
1.线程锁(互斥锁Mutex)
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,
每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁,
这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。
2.RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
3.Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,
比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
4.Timer
这个类代表一个动作,只有在一定数量的时间通过后才能运行.
5.Events
该事件表示内部标志,线程可以等待要设置标志,也可以自行设置或清除标志。
通过Event来实现两个或多个线程间的交互,
6.队列
解耦,使程序直接实现松耦合,一个程序修改不会影响其他程序
提高处理效率
队列在线程编程中特别有用,因为信息必须在多个线程之间安全地交换.。
7.生产者消费者模型
解耦
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,、
直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
1 import queue 2 import threading 3 import time 4 5 q = queue.Queue(maxsize=10) 6 7 def Producer(name): 8 count = 1 9 while True: 10 q.put("骨头%s"%count) 11 print("生产了%s骨头"%count) 12 count+=1 13 time.sleep(0.5) 14 15 16 def Consumer(name): 17 while True: 18 print("[%s]取到了[%s]并且吃了它"%(name,q.get())) 19 20 p = threading.Thread(target=Producer,args=("alex",)) 21 c = threading.Thread(target=Consumer,args=("abc",)) 22 23 p.start() 24 c.start()
多线程的使用场景
IO操作不占用CPU,计算占用CUP
Python的多线程,不适合CPU密集型操作的任务,适合IO操作密集型的任务(socket)
浙公网安备 33010602011771号