刘沙河 刘沙河
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希

花开半夏,半夏花开
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希
  • Python基础

  • Python进阶

  • Python并发编程

    • 并发编程初识
    • 进程
    • Process模块&锁&进程之间通信
    • 生产者消费者模型
    • 线程-锁&池
    • 协程
      • 1.协程的概念
      • 2.协程操作(模块)
        • 2.1 gevent 第三方模块
        • 2.2 asyncio 内置模块(记住启动一个/多个线程)
  • Django

  • Flask

  • 爬虫

  • Python
  • Python并发编程
bigox
2021-03-22
目录

协程

  • 协程和线程
    #共同点:
        -线程和协程的创建,切换销毁都需要时间开销,
        -在cpython中线程和协程都不能利用多个cpu(只能并发)
    #不同点:
        -多线程线程的切换是由操作系统完成,而协程的切换是通过代码实现,操作系统不可见
        -多线程创建,切换销毁时间开销较大,协程的时间开销很小,携程切换用户可操作性,不会增加操作系统压力
    
    1
    2
    3
    4
    5
    6
    7
  • #进程:
    开销大,数据隔离,是cpu最小的资源分配单位,至少有一个线程,cpython可以并行
    #线程:
    开销小,数据共享,是cpu最小的调度单位,是进程的一部分,cpython下只可以并发
    
    1
    2
    3
    4
    互斥锁和递归锁
    #相同点:
    1.都是一种锁
    2.都是为了解决数据安全隐患
    #不同点:
    Lock-互斥锁  不能在一个线程中连续acquire,效率相对高
    Rlock-递归锁  可以在一个线程中连续acquire,效率相对低
    
    1
    2
    3
    4
    5
    6
    7
    #简述 进程、线程、协程的区别 以及应用场景?
    进程:开销大,数据隔离,是cpu最小的资源分配单位,至少有一个线程,cpython可以并行,程序开启时就开启了一个进程
    线程:开销小,数据共享,是cpu最小的调度单位,是进程的一部分,cpython下只可以并发
    协程:开销小,不能并行,只能并发,可以使一个线程下的多个任务再碰见IO操作时,交替执行,提高效率
    #应用场景:
    程序的开启就开启了进程,
    一个单独的子线程去做一件事,分析网页,没有什么io操作就可以单独开线程
    大量任务等待去做要求一定的并发,而且有很多的IO操作就要尽可能使用协程
    
    1
    2
    3
    4
    5
    6
    7
    8
    # 操作系统
        # 1.计算机中所有的资源都是由操作系统分配的
        # 2.操作系统调度任务:时间分片、多道机制
        # 3.CPU的利用率是我们努力的指标
    # 并发
        # 进程 开销大 数据隔离 资源分配单位 cpython下可以利用多核
            # 进程的三状态:就绪 运行 阻塞
            # multiprocessing模块
                # Process-开启进程
                # Lock - 互斥锁
                    # 为什么要在进程中加锁
                        # 因为进程操作文件也会发生数据不安全
                # Queue -队列 IPC机制(Pipe,redis,memcache,rabbitmq,kafka)
                    # 生产者消费者模型
                # Manager - 提供数据共享机制
        # 线程 开销小 数据共享 cpu调度单位  cpython下不能利用多核
            # GIL锁
                # 全局解释器锁
                # Cpython解释器提供的
                # 导致了一个进程中多个线程同一时刻只有一个线程能当问CPU -- 多线程不能利用多核
            # threading
                # Thread类 - 能开启线程start,等待线程结束join
                # Lock-互斥锁  不能在一个线程中连续acquire,效率相对高
                # Rlock-递归锁  可以在一个线程中连续acquire,效率相对低
                # 死锁现象如何发生?如何避免?
            # 线程队列 queue模块
                # Queue
                # LifoQueue
                # PriorityQueue
        # 池
            # concurrent.futrues.ThreadPoolExecutor,ProcessPoolExecutor
                # 实例化一个池 tp = ThreadPoolExecutor(num),pp = ProcessPoolExecutor(num)
                # 提交任务到池中,返回一个对象 obj = tp.submit(func,arg1,arg2...)
                    # 使用这个对象获取返回值 obj.result()
                    # 回调函数 obj.add_done_callback(函调函数)
                # 阻塞等待池中的任务都结束 tp.shutdown()
       #协程全部!
    # 概念
        # IO操作
        # 同步异步
        # 阻塞非阻塞
    
    # 1.所有讲过的概念都记住
    # 2.数据安全问题
    # 3.数据隔离和通信
    # 4.会用基本的进程 线程 池
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46

# 1.协程的概念

  • 能够在一个线程下的多个任务之间来回切换,那么每一个任务就是协程

![1558063115300](C:\Users\big cattle\AppData\Roaming\Typora\typora-user-images\1558063115300.png)

进程和线程的切换是由操作系统控制切换

  • 协程和线程
    #共同点:
        -线程和协程的创建,切换销毁都需要时间开销,
        -在cpython中线程和协程都不能利用多个cpu(只能并发)
    #不同点:
        -多线程线程的切换是由操作系统完成,而协程的切换是通过代码实现,操作系统不可见
        -多线程创建,切换销毁时间开销较大,协程的时间开销很小,携程切换用户可操作性,不会增加操作系统压力
    
    1
    2
    3
    4
    5
    6
    7

# 2.协程操作(模块)

  • 线程切换

    • 两种切换方式

      两种切换方式
          # 原生python完成   yield  asyncio
          # C语言完成的python模块  greenlet  gevent
      
      1
      2
      3
      • 原生python代码实现 (asyncos 模块)- asyncos利用yield记录线程代码执行状态和位置,但是yield不能规避io操作

      • C语言完成的PYthon模块(#greenlet模块)

  • 规避IO操作,切换原理(了解)

    ![1558067064860](C:\Users\big cattle\AppData\Roaming\Typora\typora-user-images\1558067064860.png)

# 2.1 gevent 第三方模块

  • 基本格式

    import time
    import gevent
    from gevent import monkey			
    monkey.patch_all()				#用mokey模块使协程识别多次使用的外部方法,比如time.time()
    def eat():
        print('wusir is eating')
        time.sleep(1)
        print('wusir finished eat')
    
    def sleep():
        print('小马哥 is sleeping')
        time.sleep(1)
        print('小马哥 finished sleep')
    
    # g1 = gevent.spawn(eat)   # 创造一个协程任务
    # g2 = gevent.spawn(sleep)   # 创造一个协程任务
    # print(g1.value)
    # print(g2.value)
    # # g1.join()   # 阻塞 直到g1任务完成为止
    # # g2.join()   # 阻塞 直到g1任务完成为止
    # gevent.joinall([g1,g2,g3])		#知道列表内的协程任务全部终止为止
    g_l = []
    for i in range(10):
        g = gevent.spawn(eat)
        g_l.append(g)
    gevent.joinall(g_l)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
  • 接收返回值

    • value

      # g1 = gevent.spawn(eat)  # 创造一个协程任务
      # g2 = gevent.spawn(sleep)  # 创造一个协程任务 
      # print(g2.value)
      
      1
      2
      3

# 2.2 asyncio 内置模块(记住启动一个/多个线程)

  • async-异步 sync-同步

  • asyncio 协程基本格式

    #起一个任务
    
    import asyncio			#插入asyncio模块
    async def demo():		#创建async函数
          print('start')
          await asyncio.sleep(1)	#阻塞,阻塞必须写入await之后	且使用asyncio模块自己的方法
          print('end')
      loop = asyncio.get_event_loop()   #创建一个第三方事件循环,监测是否IO
      loop.run_until_complete(demo())		#吧demo任务丢到事件循环中去执行
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

#起多个任务,且没有返回值

import asyncio

async def demo(): print('start') await asyncio.sleep(1) #阻塞,阻塞必须写入await之后 且使用asyncio模块自己的方法 print('end')

loop = asyncio.get_event_loop() wait_obj=asyncio.wait([demo(),demo(),demo()]) loop.run_until_complete(wait_obj)




```python
#起多个任务,有返回值(了解)

import asyncio 
asrnc def demo():
	print('start')
    await asyncio.sleep(1)	#阻塞,阻塞必须写入await之后	且使用asyncio模块自己的方法
    print('end')
    retunrn 123

loop = asyncio.get-event_loop()
t1 = loop.create_task(demo())
t2 = loop.create_task(demo())
tasks=[t1,t2]
wait_obj=asyncio.wait([t1,t2])
loop.run_until_complete(wait_obj)
for i in easks:
print(tasks.result())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  • asyncos是python原生的底层的协程模块

    • 爬虫,webserver框架
    • 爬虫网络编程的效率和并发效果
  • await 阻塞必须写在await之后,告诉协程函数这里要切换出去,还能保证一会再切回来

  • await 必须写在async函数里,async是协程函数

  • loop 时间循环

    • 所有的协程的执行,调度都离不开这个loop
#Python#
上次更新: 2023/04/16, 18:35:33
线程-锁&池
django 常见命令

← 线程-锁&池 django 常见命令→

最近更新
01
go与http代理
05-24
02
自制申威架构k8s-reloader
12-06
03
Docker Buildx 教程
12-01
更多文章>
Theme by Vdoing | Copyright © 2020-2024 小刘扎扎 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式