标签:字典 竞争 遇到 全局变量 多个 延时 python多进程 python let
| # 多任务-进程/线程/协程 |
|---|
| ## 1.多任务的概念 |
| ### 1.1 并行和并发 |
| - 单核cpu实现多任务 |
| - 时间片轮转 |
| - 每个任务执行很短的时间 |
| - 假的多任务 |
| - 并发 |
|  |
| - 多核cpu实现多任务 |
| - 当运行的程序小于cpu核数 |
| - 不用再去轮转执行 |
| - 这就是并行 |
|  |
| - 一般情况下都是并发 |
| ## 2.多任务之线程 |
| - 多线程是实现多任务比较轻便的方式 |
| ### 2.1 多线程的使用步骤 |
| - 函数的执行 |
| ```python |
| import threading |
| def test1(g_nums): |
| def test2(): |
| def main(): |
| t2 = threading.Thread(target=test2) |
| t2.start() |
| print(threading.enumerate()) # 查看进程数量 |
| if name == "main": |
| ``` |
| - 类的执行 |
| ```python |
| # 通过继承threading.Thread和重写run()方法可以实现类的线程执行,其原理就是继承 |
| import threading |
| import time |
| class Mythread(threading.Thread): |
| if name == "main": |
| t = Mythread() |
| t.start |
| ``` |
| - target指定执行什么函数 |
| - args表示传递什么参数 是一个元组 |
| ### 2.2 多线程的创建和死亡 |
| - 线程的创建 |
| - 调用线程threading.Thread对象是创建一个对象 |
| - 只有开始threading.Thread.start()方法的时候线程才会创建并且开始运行 |
| - 线程的结束 |
| - 如果threading.Tread指定的函数执行结束,那么这个线程就结束了 |
| - 主线程会默认等待所有子线程执行结束后它才结束 |
| - 如果主线程不小心挂了,子线程也就挂了 |
| ### 2.3 线程之间共享全局变量 |
| - 多任务往往配合使用 |
| - 所以共享全局变量 |
| - 在一个函数中对全局变量修改是否要加global要看全局变量的指向是不是改变 |
| - 如果只是修改了数据,不用加gloabl |
| - 如果修改了纸箱则要加global |
| ### 2.4 多线程的问题-共享全局变量的问题 |
| - 多线程共享全局变量而且同时操作全局变量 有时候会出现资源竞争 |
|  |
| - 解决方法一:互斥锁 |
| - 利用原子性(要么不执行要么执行完) |
| - 通过互斥锁来解决这个问题 |
| - 在写操作之前加锁 |
| - 在操作之后释放锁 |
| ```python |
| # 创建锁 |
| metux = threading.lock() |
| # 加锁 |
| metux.acquire() |
| # 释放锁 |
| metux.release() |
| ``` |
|  |
| - 解决方法二:优化 只在写操作的时候加锁子 |
|  |
| ### 2.5 多线程的问题-多个互斥锁的死锁问题 |
| - 你等我,我等你就会出现死锁的问题 |
| - 如何避免死锁 |
| - 添加超时时间 |
| - 从程序的角度避免多个人写-银行家算法 |
| ## 3.多任务之进程 |
| ### 3.1 程序和进程 |
| - 程序:程序就是一个没有执行的类似于xxx.exe的东西 |
| - 进程:程序的代码+分配的资源就是进程 |
| ### 3.2 进程的状态 |
| - 新建 |
| - 就绪 |
| - 运行 |
| - 死亡 |
| - 等待 |
|  |
| ### 3.3 多进程的使用步骤 |
| ```python |
| # import threading |
| import multiprocessing |
| def test1(): |
| def test2(): |
| def main(): |
| p2 = multiprocessing.Process(target=test2) |
| p2.start() |
| if name == "main": |
| ``` |
| ### 3.4 多进程的问题 |
|  |
| - 多进程相当于代码copy多份+占用资源共同执行。所以进程的耗费资源很大。 |
| - copy的信息中还有类似pid这样的信息是不一样的 |
| - python多进程具有c语言写时拷贝的特点 只有修改的时候才会去copy |
| ### 3.5 进程之间的通信 |
| #### 3.5.1 socket |
| #### 3.5.2 queue |
| - 简单的队列可以在同台机器上实现进程之间的通信 |
| - redis及其他高级队列可以跨机器 |
|  |
| #### 3.5.3 进程池 |
| - 相当于先创建好进程 相当于mysql连接池 |
| - 多个进程的时候用进程池 |
| - 进程池可以重复利用进程池中的进程 |
| - 可以创建几个进程要和计算机硬件相关 |
|  |
| ## 4.进程和线程的对比 |
| - 代码-->进程 |
| - 进程时一坨资源和代码的总和 |
| - qq多开时多进程 |
| - 进程之中实现多任务的还是线程 |
| - 线程 |
| - 一个qq中的多个功能是线程 |
| - 一个进程中的多个任务是线程 |
| ## 5.协程 |
| ### 5.1 迭代器 |
|  |
|  |
| #### 5.1.1 可迭代对象 |
| - 可迭代对象 |
| - 列表、元祖、字典、集合、字符串 |
- 如果一个对象要是可迭代对象,那它必须有__iter__方法 |
| ```python |
| from collections import Iterable |
| isinstance([11,22,33],Iterable) # True |
| isinstance((11,22,33),Iterable) # True |
| isinstance({‘a‘:11,‘b‘:22,‘c‘:33},Iterable) # True |
| isinstance(‘112233‘,Iterable) # True |
| ``` |
| #### 5.1.2 迭代器 |
|  |
| - 迭代器 |
- 如果一个对象实现了__iter__和__next__方法,那它就是一个迭代器 |
| #### 5.1.3 迭代器的应用 |
| - 要保存数据的两种方式 |
| - 先创造并保存数据(数据)--- 鱼 |
| - 先生成一个迭代器(创造数据的工具)---- 鱼竿 |
| - 斐波那契数列 |
| - 第一种--列表 |
| ```python |
| nums = [] |
| a = 0 |
| b = 1 |
| i = 0 |
| while i<10: |
| nums.append(a) |
| a,b = b,a+b |
| i += 1 |
| for num in nums: |
| print(num) |
| ``` |
| - 第二种--迭代器 |
| ```python |
| class Fibonacci(object): |
| fibo = Fibonacci(10) |
| for num in fibo: |
| ``` |
| ### 5.2 生成器 |
| - 生成器是特殊的迭代器 |
| - 生成器的实现方式一: |
| ```python |
| [x*2 for x in range(10)] # 迭代器 |
| (x*2 for x in range(10)) # 生成器 |
| ``` |
| - 函数汇总有yeild自动变成生成器 |
| - 只要有yeild就是生成器 |
| - 生成器的实现方式二: |
| ```python |
| def create_num(all_num): |
| a, b =0, 1 |
| current_num = 0 |
| while current_num < all_num: |
| a, b = b, a+b |
| current_num += 1 |
| obj = create_num(10) |
| res = next(obj) |
| print(res) |
| ``` |
|  |
| ### 5.3 协程-yield |
| - 通过yield实现协程-多任务 |
| ```python |
| import time |
| def task_1(): |
| yield |
| def task_2(): |
| yield # 函数中有yield相当于变成了一个生成器 |
| def main(): |
| t2 = task_2() |
| while True: |
| next(t2) |
| if name == "main": |
| ``` |
| ### 5.4 协程-greenlet |
| - greenlet替换yield |
| ```shell |
| sudo pip3 install greenlet |
| ``` |
| ```python |
| from greenlet import greenlet |
| import time |
| def task_1(): |
| time.sleep(1) |
| def task_2(): |
| time.sleep(1) |
| gr1 = greenlet(test1) |
| gr2 = greenlet(test2) |
| gr1.switch() |
| ``` |
| ### 5.5 协程-gevent |
| - gevent实现协程并发 |
| ```shell |
| sudo pip3 install gevent |
| ``` |
| ```python |
| import gevent |
| def f(n): |
| g1 = gevent.spawn(f, 5) |
| g2 = gevent.spawn(f, 5) |
| g3 = gevent.spawn(f, 5) |
| g1.join() |
| g2.join() |
| g3.join() |
| ``` |
| - gevent的特点 |
| - 遇到延时操作gevent就会切换任务 |
| - gevent.sleep(0.1) |
| - gevent封装了greenlet |
| - greenlet封装了yield |
| - 给代码打补丁 |
| ```python |
| import gevent |
| from gevent import monkey |
| monkey.patch_all() |
| def f(n): |
| g1 = gevent.spawn(f, 5) |
| g2 = gevent.spawn(f, 5) |
| g3 = gevent.spawn(f, 5) |
| g1.join() |
| g2.join() |
| g3.join() |
| ``` |
| ## 6.进程、线程、协程对比 |
| - 进程是资源分配的最小单位 |
| - 代码+操作系统的资源 |
| - 线程是操作系统调度的最小单位 |
| - 进程之间的切需要很大的资源,效率低 |
| - 线程切换需要的资源一般,效率一般 |
| - 协程切换任务资源很小、效率更高 |
| - 进程和线程根据cpu核心数和任务的数量,可能是并行也可能是并发、协程一定是并发、 |
标签:字典 竞争 遇到 全局变量 多个 延时 python多进程 python let
原文地址:https://www.cnblogs.com/gokublog/p/14682175.html