操作系统-协程模块

线程
cpython解释下的多个线程不能利用多核:规避了所有io操作的单线程
协程
是操作系统不可见的
协程本质是一条线程,多个任务在一条线程上来回切换,
利用协程这个概念实现的内容:来规避IO操作,就达到了我们将一条线程中的io操作降到最低的目的

 import time
def func1():
    print('start')
    time.sleep(1)
    print('end')
def func2():
    print('start')
    time.sleep(1)
    print('end')

逻辑问题,先开func1 func1 sleep(I/O)操作的时候 执行func2中的代码 发现func2
也有sleep(I/O)操作可以再切到其他任务
什么时候回来:记录时间,睡一秒后再回来

切换并规避IO的两个模块
gevent模块:利用了greenlet底层模块完成切换+自动规避io的功能
asyncio模块:利用了 yield 底层语法完成的切换+自动规避io的功能
yield from去实现协程 send更好实现协程
在python中提供协程功能的关键字:async await
进程 数据隔离 数据不安全 操作系统级别 开销非常大 cpython 能利用多核
线程 数据共享 数据不安全 操作系统级别 开销小 cpython不能利用多核
一些和文件操作相关的io只有操作系统能感知到
协程 数据共享 数据安全(用户级别切换)更小 cpython不能利用多核 协程所有切换都基于用户
只有在用户级别能够感知到的io操作才会用写成模块来规避(网络操作,socket,请求网页,sleep)
用户级别的协程有什么好处?
减小操作系统的负担
一条线程如果开了多个协程,那么给操作系统的印象是线程很忙,这样能够争取一些时间片来被CPU执行
程序的效率就提高了

对于操作系统:python代码–》编译-字节码-解释–》二进制000011111
4cpu
进程 5个进程
线程 20个
协程 500个
520500=50000
协程的例子

 from gevent import monkey
monkey.patch_all()
import gevent
import asyncio
import time


def func():  # 带有io操作的内容写在函数里,然后提交func给gevent
    print('start func')
    # gevent.sleep(1)
    time.sleep(1)
    print('end func')


g1 = gevent.spawn(func)
g2 = gevent.spawn(func)
g3 = gevent.spawn(func)
gevent.joinall([g1, g2, g3])
 g1.join()  # 阻塞直到协程g1任务执行结束
 gevent.sleep(2)

基于gevent协程实现socket并发
server

from gevent import monkey

monkey.patch_all()
import socket

import gevent


def func(conn):
    while True:
        msg = conn.recv(1024).decode('utf-8')
        MSG = msg.upper()
        conn.send(MSG.encode('utf-8'))


sk = socket.socket()
sk.bind(('127.0.0.1', 9000))
sk.listen()
while True:
    conn, _ = sk.accept()
    gevent.spawn(func, conn)

client

import socket
import time
from threading import Thread


def client():
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    while True:
        sk.send(b'hello')
        msg = sk.recv(1024)
        print(msg)
        time.sleep(0.5)


for i in range(500):
    Thread(target=client).start()

asynico模块

import socket
import time
from threading import Thread


def client():
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    while True:
        sk.send(b'hello')
        msg = sk.recv(1024)
        print(msg)
        time.sleep(0.5)


for i in range(500):
    Thread(target=client).start()

asynico实现原理

# 协程的原理
# yield
# def func():
#     print(123)
#     yield
#     print(456)
# g=func()
# next(g)#切出去
# next(g)#切回来
import time


def sleep(n):
    print('start sleep')
    yield time.time() + n
    print('end sleep')


def func(n):
    print(123)
    gen = sleep(n)
    yield from gen  # yield vs yield from
    print(456)


n = 1
g1 = func(n)
g2 = func(n)
ret1 = next(g1)  # 切出去
ret2 = next(g2)
# print('--->',ret)
# time.sleep(ret-time.time())
# next(g)  # 切回来
time_lst = {ret1: g1, ret2: g2}
print('--->', time_lst)
while time_lst:
    min_time = min(time_lst)
    time.sleep(min_time - time.time())
    try:
        next(time_lst[min_time])
    except StopIteration:
        pass
    del time_lst[min_time]

# 网络编程:会起tcp协议,udp协议
# 并发编程 会起进程 线程 协程
# 概念 相关模块 最起码的启停机制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值