标签:字典 竞争 遇到 全局变量 多个 延时 python多进程 python let
# 多任务-进程/线程/协程 |
---|
## 1.多任务的概念 |
### 1.1 并行和并发 |
- 单核cpu实现多任务 |
- 时间片轮转 |
- 每个任务执行很短的时间 |
- 假的多任务 |
- 并发 |
![image-20210316235023692](/Users/huhao/Library/Application Support/typora-user-images/image-20210316235023692.png) |
- 多核cpu实现多任务 |
- 当运行的程序小于cpu核数 |
- 不用再去轮转执行 |
- 这就是并行 |
![image-20210316235227274](/Users/huhao/Library/Application Support/typora-user-images/image-20210316235227274.png) |
- 一般情况下都是并发 |
## 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 多线程的问题-共享全局变量的问题 |
- 多线程共享全局变量而且同时操作全局变量 有时候会出现资源竞争 |
![image-20210317005813818](/Users/huhao/Library/Application Support/typora-user-images/image-20210317005813818.png) |
- 解决方法一:互斥锁 |
- 利用原子性(要么不执行要么执行完) |
- 通过互斥锁来解决这个问题 |
- 在写操作之前加锁 |
- 在操作之后释放锁 |
```python |
# 创建锁 |
metux = threading.lock() |
# 加锁 |
metux.acquire() |
# 释放锁 |
metux.release() |
``` |
![image-20210317010822185](/Users/huhao/Library/Application Support/typora-user-images/image-20210317010822185.png) |
- 解决方法二:优化 只在写操作的时候加锁子 |
![image-20210317011138982](/Users/huhao/Library/Application Support/typora-user-images/image-20210317011138982.png) |
### 2.5 多线程的问题-多个互斥锁的死锁问题 |
- 你等我,我等你就会出现死锁的问题 |
- 如何避免死锁 |
- 添加超时时间 |
- 从程序的角度避免多个人写-银行家算法 |
## 3.多任务之进程 |
### 3.1 程序和进程 |
- 程序:程序就是一个没有执行的类似于xxx.exe的东西 |
- 进程:程序的代码+分配的资源就是进程 |
### 3.2 进程的状态 |
- 新建 |
- 就绪 |
- 运行 |
- 死亡 |
- 等待 |
![image-20210317131843032](/Users/huhao/Library/Application Support/typora-user-images/image-20210317131843032.png) |
### 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 多进程的问题 |
![image-20210317132749018](/Users/huhao/Library/Application Support/typora-user-images/image-20210317132749018.png) |
- 多进程相当于代码copy多份+占用资源共同执行。所以进程的耗费资源很大。 |
- copy的信息中还有类似pid这样的信息是不一样的 |
- python多进程具有c语言写时拷贝的特点 只有修改的时候才会去copy |
### 3.5 进程之间的通信 |
#### 3.5.1 socket |
#### 3.5.2 queue |
- 简单的队列可以在同台机器上实现进程之间的通信 |
- redis及其他高级队列可以跨机器 |
![image-20210317190019772](/Users/huhao/Library/Application Support/typora-user-images/image-20210317190019772.png) |
#### 3.5.3 进程池 |
- 相当于先创建好进程 相当于mysql连接池 |
- 多个进程的时候用进程池 |
- 进程池可以重复利用进程池中的进程 |
- 可以创建几个进程要和计算机硬件相关 |
![image-20210317190438274](/Users/huhao/Library/Application Support/typora-user-images/image-20210317190438274.png) |
## 4.进程和线程的对比 |
- 代码-->进程 |
- 进程时一坨资源和代码的总和 |
- qq多开时多进程 |
- 进程之中实现多任务的还是线程 |
- 线程 |
- 一个qq中的多个功能是线程 |
- 一个进程中的多个任务是线程 |
## 5.协程 |
### 5.1 迭代器 |
![image-20210318183103647](/Users/huhao/Library/Application Support/typora-user-images/image-20210318183103647.png) |
![image-20210318183305098](/Users/huhao/Library/Application Support/typora-user-images/image-20210318183305098.png) |
#### 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 迭代器 |
![image-20210318183404142](/Users/huhao/Library/Application Support/typora-user-images/image-20210318183404142.png) |
- 迭代器 |
- 如果一个对象实现了__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) |
``` |
![image-20210318214702428](/Users/huhao/Library/Application Support/typora-user-images/image-20210318214702428.png) |
### 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