协程

进程是资源分配的最小单位
线程是cpu调度的最小单位

进程和线程在创建的时候都需要消耗时间,还需要管理他们之间的切换

所有人的目的都是实现并发处理事情

使用单线程单进程完成并发处理

def create_num(all_num):
print(“—1—“)
a,b = 0,1
current_num = 0
while current_num < all_num:
print(“—2—“)
ret = yield a
print(“—-ret—-“,ret)
print(“—3—“)
a,b = b , a+b
current_num+=1
print(“—4—“)
pass

def main():
obj = create_num(10)
ret = next(obj)
print(ret)
ret = obj.send(“haha”)
print(ret)
pass

if name == ‘main‘:
main()
============================
import time

def task_1():
while True:
print(“—1—“)
time.sleep(1)
yield
pass

def task_2():
while True:
print(“—2—“)
time.sleep(2)
yield
pass

def main():
t1 = task_1()
t2 = task_2()

  1. while True:<br /> next(t1)<br /> next(t2)<br /> pass

if name == ‘main‘:
main()
==============================

协程是可以用户自己调度的,是一个轻量级线程

单线程内开启协程,如果碰到了io,就会从应用程序这个级别进行切换

所以协程开销很小,属于程序级别的切换,操作系统感知不到,所以协程是真的轻量级

单线程内实现最大的并发效果,最大程度利用cpu


但是协程本质是单线程的,无法利用多核,所以可以考虑一个程序开多个进程,一个进程开多个线程,每个线程开协程

一般协程指单个线程,一旦协程出现了阻塞,就会整个程序阻塞


修改共享的数据不要加锁

=================================

import time
from greenlet import greenlet

def f1():
res = 1
for i in range(10000000):
res +=1
time.sleep(1)
print(res)
g2.switch()
pass

def f2():
res = 1
for i in range(20000000):
res +=2
time.sleep(1)
print(res)
g1.switch() #此时这个函数的结果凝固,切换到另一个地方
pass

start = time.time()
g1 = greenlet(f1)
g2 = greenlet(f2)
g2.switch() #先开始谁
stop = time.time()
print(stop-start) #1.624s

=======================

import time
from greenlet import greenlet

def f1(g2,g1):
res = 1
for i in range(10000000):
res +=1
time.sleep(1)
print(res)
g2.switch(g1,g2)
pass

def f2(g1,g2):
res = 1
for i in range(20000000):
res +=2
time.sleep(1)
print(res)
g1.switch(g2,g1)
pass

def main():
start = time.time()
g1 = greenlet(f1)
g2 = greenlet(f2)
g2.switch(g1,g2)
stop = time.time()
print(stop - start) # 如果不用greenlet是1.624s,如果用就5s多,并没有解决效率的问题
pass

if name == ‘main‘:
main()
—————————————————

因为greenlet没法解决效率问题,所以用gevent,gevent可以以后用来当协程池,是对greenlet的一个封装

如果不打补丁,就要用gevent.sleep(1) #模拟io阻塞,如果不用模拟io阻塞又不打补丁,就是正常执行规律

from gevent import monkey;monkey.patch_all() #打补丁
import gevent,time

def eat(name):
print(“%s eat 1”%name)
#gevent.sleep(1) #模拟io阻塞
time.sleep(1)
print(“%s eat 2” % name)
pass

def play(name):
print(“%s play 1”%name)
#gevent.sleep(1)
time.sleep(2)
print(“%s play 2” % name)
pass

def main():
g1 = gevent.spawn(eat,’xiaoming’)
g2 = gevent.spawn(play,’xiaohong’)
#g1.join()
#g2.join()
gevent.joinall([g1,g2])
print(“main”)
pass

if name == ‘main‘:
main()

from gevent import monkey;monkey.patch_all() #打补丁
import threading
import gevent,time

def eat(name):
print(threading.current_thread().getName())#显示假线程!!!
print(“%s eat 1”%name)
#gevent.sleep(1) #模拟io阻塞
time.sleep(1)
print(“%s eat 2” % name)
pass

def play(name):
print(threading.current_thread().getName())
print(“%s play 1”%name)
#gevent.sleep(1)
time.sleep(2)
print(“%s play 2” % name)
pass

def main():
g1 = gevent.spawn(eat,’xiaoming’)
g2 = gevent.spawn(play,’xiaohong’)
#g1.join()
#g2.join()
gevent.joinall([g1,g2])
print(“main”)
pass

if name == ‘main‘:
main()
================================

from gevent import spawn,joinall,monkey;monkey.patch_all() #打补丁
import time

def task(pid):
time.sleep(0.5)
print(“task %s done”%pid)
pass

同步
def sync():
for i in range(10):
task(i)
pass

异步
def asynch():
g_1 = [spawn(task,i) for i in range(10)]
joinall(g_1)
print(‘done’)
pass

def main():
#sync() #按流程去做
asynch() #使用协程创建假线程最快速度完成
pass

if name == ‘main‘:
main()
=======================================