GIL解释器,协程,gevent模块
GIL解释器锁
在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL
GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。
可以肯定的一点是:保护不同的数据的安全,就应该加不同的锁。
每一个cpython进程内都有一个GIL
GIL导致同一进程内的多个线程同一时间只能有一个运行
之所以有GIL,是因为cpython的内存管理不是线程安全的
对于计算密集型用多进程,对于IO密集型用多线程
死锁和递归锁
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁

from threading import Thread,Lock,RLock
import time
# mutexA = Lock()
# mutexB = Lock()
mutexA = mutexB = RLock() # 一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止 class MyThread(Thread):
def run(self):
self.f1()
self.f2() def f1(self):
mutexA.acquire()
print('%s 拿到A锁'%self.name)
mutexB.acquire()
print('%s 拿到A锁' % self.name)
mutexB.release()
mutexA.release()
def f2(self):
mutexB.acquire()
print('%s 拿到B锁'%self.name)
time.sleep(0.1)
mutexA.acquire()
print('%s 拿到A锁' % self.name)
mutexA.release()
mutexB.release() if __name__ == '__main__':
for i in range(10):
t = MyThread()
t.start()

协程
协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的
利用yield实现单线程下的并发

import time
def consumer():
'''任务1:接收数据,处理数据'''
while True:
x=yield def producer():
'''任务2:生产数据'''
g = consumer()
next(g)
for i in range(10000000):
g.send(i) start = time.time()
# 基于yield保存状态,实现两个任务直接来回切换,即并发的效果
# PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
producer() stop = time.time()
print(stop-start) # 2.0272178649902344

gevent模块
time.sleep(2)或其他的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了
from gevent import monkey;monkey.patch_all()必须放到被打补丁者的前面,如time,socket模块之前
或者我们干脆记忆成:要用gevent,需要将from gevent import monkey;monkey.patch_all()放到文件的开头

# pip3 install gevent
# 1.切换+保存状态
# 2.检测IO,实现遇到IO切换
from gevent import monkey
monkey.patch_all() # 将程序中的所有IO操作打标记,使gevent能识别
import gevent
import time def eat(name):
print('%s eat 1'%name)
time.sleep(2)
print('%s eat 2' % name)
def play(name):
print('%s play 1'%name)
time.sleep(3)
print('%s play 2' % name) g1 = gevent.spawn(eat,'alex')
g2 = gevent.spawn(play,'egon') g1.join()
g2.join()

GIL解释器,协程,gevent模块的更多相关文章
- 协程:gevent模块,遇到i/o自动切换任务 038
协程 : gevent模块,遇到io自动切换任务 from gevent import monkey;monkey.patch_all() # 写在最上面 这样后面的所有阻塞就全部能够识别了 impo ...
- python编程中的并发------协程gevent模块
任务例子:喝水.吃饭动作需要耗时1S 单任务:(耗时20s) for i in range(10): print('a正在喝水') time.sleep(1) print('a正在吃饭') time. ...
- 协程--gevent模块(单线程高并发)
先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行.这种 ...
- python之协程gevent模块
Gevent官网文档地址:http://www.gevent.org/contents.html 进程.线程.协程区分 我们通常所说的协程Coroutine其实是corporate routine的缩 ...
- python 并发编程 协程 gevent模块
一 gevent模块 gevent应用场景: 单线程下,多个任务,io密集型程序 安装 pip3 install gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...
- 协程gevent模块和猴子补丁
# pip 装模块 greenlet和gevent # 协程 # 与进程.线程一样也是实现并发的手段 # 创建一个线程.关闭一个线程都需要创建寄存器.栈等.需要消耗时间 # 协程本质上是一个线程 # ...
- 协程----greenlet模块,gevent模块
1.协程初识,greenlet模块 2.gevent模块(需要pip安装) 一.协程初识,greenlet模块: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线 ...
- GIL以及协程
GIL以及协程 一.GIL全局解释器锁 演示 ''' python解释器: - Cpython c语言 - Jpython java 1.GIL:全局解释器锁 - 翻译:在同一个进程下开启的多个线程, ...
- python 线程(其他方法,队列,线程池,协程 greenlet模块 gevent模块)
1.线程的其他方法 from threading import Thread,current_thread import time import threading def f1(n): time.s ...
- 14 并发编程-(协程)-greenlet模块&gevent模块
1.实现多个任务之间进行切换,yield.greenlet都没有实现检测I/O,greenlet在实现多任务切换下更简单 from greenlet import greenlet def eat(n ...
随机推荐
- 如何在openwrt上实现 U盘的自动挂载
U盘的自动挂载,分为两种场景 1.路由器先上电,然后插上U盘并自动挂载 2.路由器先插上U盘,然后上电并自动挂载 上述场景的实现,需要如下几个步骤: 1.支持如下模块: USB驱动模块:USB OHC ...
- Socket创建失败:10093错误
10093的错误,应用程序没有调用 WSAStartup,或者 WSAStartup 失败. 问题描述:Failed to create UDP socket:10093!Close and rest ...
- import _mysql----ImportError: DLL load failed: %1 不是有效的 Win32 应用程序。
背景:安装了mysql,练习sql 操作,提示 ImportError DLL load failed: %1 不是有效的 Win32 应用程序 解决方法: 操作系统win10,64位,查看安装的my ...
- 谈谈对XML的理解?说明Web应用中Web.xml文件的作用?
谈谈对XML的理解?说明Web应用中Web.xml文件的作用? 解答:XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard ...
- 【BZOJ】3315: [Usaco2013 Nov]Pogo-Cow(dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=3315 果然自己太弱. 想不出dp方程啊.. 其实,以后记住...与上一个状态或下一个状态有关,,可以 ...
- sql server生成不重复的时间字符串
),REPLACE(CONVERT(,),GETDATE()),'.',''))
- 20个JS 小技巧超级实用
1. 将彻底屏蔽鼠标右键 oncontextmenu=”window.event.returnValue=false” < table border oncontextmenu=return(f ...
- Spark源码分析(四)-Job提交过程
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3903478.html 本文将以一个简单的WordCount为例来看看Job的提交过程
- 【转】CStdioFile UNICODE编译 英文系统下读取中文汉字乱码解决
转载出处:http://www.cnblogs.com/ct0421/p/3242418.html 函数原形为:char *setlocale( int category, const char *l ...
- 国内Android源码下载
因国内网络被墙的原因,按照Google提供下载Android源码的方式很难下载到,所以记录一下国内下载Android源码的步骤,主要利用的是清华大学的镜像下载. 说明: 下载环境:Ubuntu14.0 ...