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的进程/线程/协程的更多相关文章

  1. python进阶——进程/线程/协程

    1 python线程 python中Threading模块用于提供线程相关的操作,线程是应用程序中执行的最小单元. #!/usr/bin/env python # -*- coding:utf-8 - ...

  2. Python中进程线程协程小结

    进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...

  3. Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程

    1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...

  4. Python 进程线程协程 GIL 闭包 与高阶函数(五)

    Python 进程线程协程 GIL 闭包 与高阶函数(五) 1 GIL线程全局锁 ​ 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的 ...

  5. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  6. 进程&线程&协程

    进程  一.基本概念 进程是系统资源分配的最小单位, 程序隔离的边界系统由一个个进程(程序)组成.一般情况下,包括文本区域(text region).数据区域(data region)和堆栈(stac ...

  7. 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型

    本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...

  8. python进程/线程/协程

    一 背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所 ...

  9. python-socket和进程线程协程(代码展示)

    socket # 一.socket # TCP服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bin ...

随机推荐

  1. TestNg 12. extentReport测试报告

    直接上代码:以下是我的目录结构,首先新建一个包名字叫 com.tester.extent.demo,直接新建两个类就可以,名字叫  ExtentTestNGIReporterListener  和 T ...

  2. HTML学习笔记Day14

    一.移动端页面布局 1.移动端的屏幕尺寸 移动端屏幕尺寸:屏幕对角线的长度,单位是英寸(1英寸=2.45厘米): 常见的尺寸有:2.4,2.8,3.5,3.7,4.2,5.0,5.5,6.0 2.屏幕 ...

  3. Go-day03

    概要: 1.strings与strconv的使用 2.Go中的时间和日期类型 3.流程控制 4.函数详解 strings与strconv用法 1.strings.HasPrefix(s string, ...

  4. jmeter打开图形化界面时指定代理

    \apache-jmeter-4.0\bin>jmeter -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8888 如果不想在每个请求里面指定代理的话可 ...

  5. xlrd(excel导入mysql数据库)

    一.xlrd模块: python 对 excel 文件进行读操作 1.下载xlrd 并安装 http://pypi.python.org/pypi/xlrd wget https://pypi.pyt ...

  6. OS + Linux nmon / nmon analyser / nmon_analyser_v52_1.zip

    s nmon_analyser_v52_1.zip https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/Pow ...

  7. nGrinder windows agent / linux agent

    s ngrinder部署 https://blog.csdn.net/yue530tomtom/article/details/82113558 Windows机器启动不了ngrinder-agent ...

  8. Sqlserver 数据库定时自动备份

    sqlserver 可以通过微软工具 SQL Server Management Studio  进行数据库定时自动备份,具体步骤如下: 1,打开SQL Server Management Studi ...

  9. Spring Boot笔记九:AOP面向切面编程

    我参考的这篇文章,以验证身份为例讲解了什么是AOP AOP 这里只讲解一下怎么去实现AOP 新建一个类,叫HttpAspect用来切面 package com.vae.springboot.study ...

  10. EL表达式获取日期时间类型后格式化的问题

    最近在项目中遇到的问题,就是从后台取到的java.util.Date类型的数据,在前台需要格式化的问题. 开始想了很多办法,其实在JSP页面中处理很简单,JSTL提供的format标签即可解决这个问题 ...