码迷,mamicode.com
首页 > 编程语言 > 详细

【进程-线程-协程】

时间:2021-04-21 12:57:57      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:字典   竞争   遇到   全局变量   多个   延时   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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!