概念:
python的线程属于内核级别的,即由操作系统控制调度 (如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
单线程内开启协程,一旦遇到io,就会从应用程序级别 ( 而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
协程: (简单来说就是单线程下的并发).
指的是只在同一条线程上能够相互切换多个任务,
遇到IO就切换实际上是我们利用协程提高工作效率的一种工作方式.
特点:
(纤程,轻型线程)
协程是操作系统级别的操作单位
协程的切换开销更小,属于程序级的切换,对于操作系统来说是不可见的,不需要操作系统调 度
单线程内就可以实现并发的效果,最大限度地利用cpu 修改共享数据不需要加锁
他的效率如何?
和操作系统本身没有关系,和线程也没有关系.
而是看程序的调度是否合理
缺点:
协程的本质是单线程下,无法利用多核,所以他的顺序为(一个程序开启多个进程,每个进程开启多个线程,每个线程开启协程)
协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程.
协程模块:
greelet:在多个任务之间来回切换
gevent ;也是多个任务之间切换(比上边的更强大)
用法:
import time from greenlet import greenlet ‘‘‘ def play():#协程1 print(‘娃哈哈‘) g2.switch() print(‘托儿索‘) g2.switch() def sleep(): # 协程2 print(‘喜之狼‘) g1.switch() print(‘儿童劫‘) g1=greenlet(play) g2=greenlet(sleep) g1.switch() ‘‘‘ import gevent def play():#协程1 print(‘娃哈哈‘) gevent.sleep(0.3) print(‘托儿索‘) def sleep(): # 协程2 print(‘喜之狼‘) gevent.sleep(0.2) print(‘儿童劫‘) g1=gevent.spawn(play) g2=gevent.spawn(sleep) # g1.join(0.5) # 阻塞0.5秒 # g2.join()# # 精准的控制协程任务,一定是执行完毕之后join立即结束阻塞 print(‘哈哈‘) gevent.joinall([g1,g2]) from gevent import monkey;monkey.patch_all() # 把下面所有的模块中的阻塞都打成一个包,然后gevent就可以识别这些阻塞事件了 import time import gevent def play(): # 协程1 print(time.time()) print(‘start play‘) time.sleep(1) print(‘end play‘) def sleep(): # 协程2 print(‘start sleep‘) time.sleep(1) print(‘end sleep‘) print(time.time()) g1 = gevent.spawn(play) g2 = gevent.spawn(sleep) gevent.joinall([g1,g2])
协程下实现socekt通信:
服务端:from gevent import monkey;monkey.patch_all() import socket import gevent def talk(conn): while True: msg = conn.recv(1024).decode() conn.send(msg.upper().encode()) sk = socket.socket() sk.bind((‘127.0.0.1‘,9000)) sk.listen() while True: conn,addr = sk.accept() gevent.spawn(talk,conn) 客户端: import socket import threading def task(): sk = socket.socket() sk.connect((‘127.0.0.1‘,9000)) while True: sk.send(b‘hello‘) print(sk.recv(1024)) for i in range(500): threading.Thread(target=task).start()
原文地址:https://www.cnblogs.com/systemsystem/p/10116695.html
时间: 2024-10-30 03:26:22