python的进程/线程/协程
1、python的多线程
多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有一个线程被执行。
多线程的特点:
线程比进程更轻量级,创建一个线程要比创建一个进程快10-100倍。
线程共享全局变量。
由于GIL的原因,当一个线程遇到IO操作时,会切换到另一个线程,所以线程适合IO密集型操作。
在多核cpu系统中,最大限度的利用多核,可以开启多个线程,开销比进程小的多,但是这并不适合python。
多线程互斥锁:
因为线程共享全局变量,所以需要互斥锁去限制线程对全局变量的更改。
假设,当一个线程在执行到获取全局变量的时候,这个后GIL切换到另一个线程执行,这个时候新的线程为全局变量+1后切换回之前的线程,之前的线程中的全局变量还是+1前的值,所以需要互斥锁。
为什么有了GIL锁还要互斥锁呢?
GIL锁只是控制同一时刻下只有一个线程被执行,这并不能控制同一时刻只有一个线程去获取并更改全局变量,所以需要使用互斥锁。
多线程的实现:
# 导入threading模块
import threading
# 定义全局变量
i=0
# 定义互斥锁
mutex = threading.Lock()
def a():
# 申明全局变量i
global i
for j in range(2000000):
# 获取互斥锁
mutex.acquire()
i+=1
# 释放互斥锁
mutex.release() def b():
global i
for j in range(2000000):
mutex.acquire()
i+=1
mutex.release()
# 创建线程
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
# 开启线程
t1.start()
t2.start()
# 等待所有线程结束
t1.join()
t2.join()
print(i)
2、python中的多进程
python的多线程不能利用多核的优势,如果想要充分的利用多核cpu的资源,python中大部分情况需要使用多进程。
python多进程的特点:
进程间不共享全局变量,进程修改的数据仅限于该进程内。
进程创建和销毁的开销比较大。
相对于线程,进程更适合与计算密集型操作。
能充分利用多核的优势。
进程间通信:
既然进程间中不公共享全局变量,那么多进程间怎么进行通信呢?可以使用multiprocessing中的Queue模块,当然也可以使用socket、管道、共享内存等方式。
多进程的实现:
# 导入multiprocessin模块
import multiprocessing
# 创建队列
queue = multiprocessing.Queue()
# 定义全局变量
a = 0
# 定义函数
def work1(num):
# 获取队列中的数据,如果没有数据,将堵塞
a = queue.get()
# 将队列中的数据+2000000次num
for i in range(2000000):
a+=num
# 将数据存放在队列中
queue.put(a)
# 打印最终结果
print("work1",a)
# 定义函数
def work2():
# 申明全局变量a
global a
# 将a+2000000次1
for i in range(2000000):
a+=1
# 打印最总结果
print("work2",a)
# 将a存放在队列中
queue.put(a)
# 创建进程
p1 = multiprocessing.Process(target=work1, args=(2,))
p2 = multiprocessing.Process(target=work2)
# 启动进程
p1.start()
p2.start()
# 等待进程结束
p1.join()
p2.join()
# 获取队列中的数据
a = queue.get()
# 打印a
print(a)
进程池的实现
进程池能减少重复创建和销毁进程的开销问题
# 导入需要的模块
import multiprocessing
import time
import random
# 定义函数
def work(num):
print("num=",num)
time.sleep(random.randint(0,2))
# 创建进程池,设置进程的数量
pool = multiprocessing.Pool(3)
for i in range(10):
# 开启进程
pool.apply_async(work, args=(i,))
# 设置等待时间,等待所有进程结束
time.sleep(20)
3、python中的协程
在linux中线程就是轻量级的进程,而我们通常也把协程称为轻量级的线程。
对比进程和协程:
进程是内核调度,而协程是在用户态调度,所以说进程的上下文在内核态保存恢复,而协程是在用户态保存恢复的,所以协程的开销比进程低。
进程会被抢占,而协程不会,也就是说协程如果不主动让出cpu,那么其他的协程就没有执行的机会。
进程所需要的内存比协程大得多
对比线程和协程:
线程的上下文切换成本相对于协程来说比较高。
线程的切换由操作系统来控制,而协程的切换由我们自己控制。
yield实现协程:
# 定义两个函数
def work1():
while True:
print("work1")
# 当程序运行到yield就会暂停,等待下次的next调用,然后继续执行
yield
def work2():
while True:
print("work2")
yield w1 = work1()
w2 = work2()
while True:
# 使用next函数启动
next(w1)
next(w2)
greenlet实现协程:
greenlet安装:
sudo pip3 install greenlet
code:
# 导入greenlet模块
from greenlet import greenlet
def work1():
for i in range(10):
print("work1")
# 打印过后跳转至协程g2继续执行
g2.switch() def work2():
for i in range(10):
print("work2")
# 打印后跳转至协程g1继续执行
g1.switch() # 创建协程g1
g1 = greenlet(work1)
# 创建协程g2
g2 = greenlet(work2)
# 跳转至协程g1
g1.switch()
gevent实现协程:
gevent是基于greenlet的并发网络库,每当有一个协程堵塞的时,程序将自动调度。
monkey-patching:
一般称为猴子补丁,这个补丁能直接修改标准库里面大部分的阻塞式系统调用。但是如果在复杂的生产环境中使用了这些标准库,可能就会因为打了补丁而出现奇怪的问题。
gevent安装:
sudo pip3 install gevent
code:
# 导入所需要的模块
import gevent
import time
from gevent import monkey
# 猴子补丁,monkey.patch_all()方法将所有的标准库都替换掉
# 使用猴子补丁褒贬不一,但是官网上还是建议使用patch_all(),而且在程序的第一行就执行
monkey.patch_all()
def f(n):
for i in range(n):
print(i)
# 设置延时
time.sleep(0.5)
# 如果没有导入monkey模块的话,需要使用gevent.sleep()
# gevent.sleep(0.5) # ----------------写法一--------------------
# 创建greenlet协程对象
# g1 = gevent.spawn(f,5)
# g2 = gevent.spawn(f,5)
# g3 = gevent.spawn(f,5)
# 等待所有greenlet携程结束后退出
# g1.join()
# g2.join()
# g3.join() # ----------------写法二--------------------
gevent.joinall([gevent.spawn(f,5), gevent.spawn(f,5), gevent.spawn(f,5)])
python的进程/线程/协程的更多相关文章
- python进阶——进程/线程/协程
1 python线程 python中Threading模块用于提供线程相关的操作,线程是应用程序中执行的最小单元. #!/usr/bin/env python # -*- coding:utf-8 - ...
- Python中进程线程协程小结
进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...
- Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程
1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...
- Python 进程线程协程 GIL 闭包 与高阶函数(五)
Python 进程线程协程 GIL 闭包 与高阶函数(五) 1 GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的 ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- 进程&线程&协程
进程 一.基本概念 进程是系统资源分配的最小单位, 程序隔离的边界系统由一个个进程(程序)组成.一般情况下,包括文本区域(text region).数据区域(data region)和堆栈(stac ...
- 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型
本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...
- python进程/线程/协程
一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...
- python-socket和进程线程协程(代码展示)
socket # 一.socket # TCP服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bin ...
随机推荐
- 洛谷P2050 美食节
修车加强版.发现每个厨师拆成p个点太浪费了,毕竟总共用到的才p个点.于是从下往上一个一个加,加到满流就停. 论动态加点费用流的正确姿势...... 我自己加总是出现负环...我是每次加一整层,然后跑完 ...
- 跟我一起使用android Studio打包react-native项目的APK
使用的是react-native的hello-world项目 第一步:创建项目 npm install -g yarn react-native-cli react-native init Aweso ...
- (链表) leetcode 328. Odd Even Linked List
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...
- Qt ------ window下工程项目打包成一个exe程序
最近,在学习QT5的过程中,想尝试着把自己写的工程程序给打包发布出来,在任何一台windows系统都能运行,这样就不会限于电脑需不需要安装QT安装包了. 首先,先介绍自己使用的环境.我使用的QT版本是 ...
- 字节输入流 FileInputStream
字节输入流 InputStream : 方法介绍: read(); 读取下一个字节 返回-1读取文件结束 close(); 复制文件 将数据aaa.txt复制到d盘 字节输入流读---->字节输 ...
- 字节输出流 FileOutputStream
输入和输出 : 参照物 都是java程序来参照 output 内存---->硬盘 input 持久化数据-->内存 字节流输出 定义:流按照方向可以分为输入和输出流 字节流 :可以操作任何 ...
- linux文件或目录权限修改后如何恢复(备份了权限就能恢复)
操作系统 RHEL5 如果你在linux上执行了如下操作chmod -R 777 / 或者 chmod -R 700 /那么恭喜你,你的系统即将崩溃,重启之后,你进不了图形界面,而且很多服务都起不来 ...
- kubeadm安装Kubernetes V1.10集群详细文档
https://www.kubernetes.org.cn/3808.html?tdsourcetag=s_pcqq_aiomsg 1:服务器信息以及节点介绍 系统信息:centos1708 mini ...
- jmeter5.0 while controller使用总结
while controller 配合sql使用的方式 在while控制器条件中填空,这样当里面的请求断言失败后就会跳出循环 在while控制器条件中填LAST,当里面的请求断言失败后就会跳出循环,如 ...
- 编写Excel文件的Golang库
github:https://github.com/360EntSecGroup-Skylar/excelize 使用用例 https://dev.to/xuri/go-library-for-rea ...