并发编程——全局解释器锁GIL
1.全局解释器锁GIL
GIL其实就是一把互斥锁(牺牲了效率但是保证了数据的安全)。
线程是执行单位,但是不能直接运行,需要先拿到python解释器解释之后才能被cpu执行
同一时刻同一个进程内多个线程无法实现并行,但是可以实现并发
为什么要有GIL是因为它内部的垃圾回收机制不是线程安全的
垃圾回收机制也是一个任务,跟你的代码不是串行运行,如果是串行会明显有卡顿
这个垃圾回收到底是开进程还是开线程?肯定是线程,线程肯定也是一段代码,所以想运行也必须要拿到python解释器
假设能够并行,会出现什么情况?一个线程刚好要造一个a=1的绑定关系之前,这个垃圾线程来扫描,矛盾点就来了,谁成功都不对!
也就意味着在Cpython解释器上有一把GIL全局解释器锁
同一个进程下的多个线程不能实现并行但是能够实现并发,多个进程下的线程能够实现并行
1.python中的多线程到底有没有用?
单核情况下:四个任务
多核情况下:四个任务
计算密集型:一个任务算十秒,四个进程和四个线程,肯定是进程快
IO密集型:任务都是纯io情况下,线程开销比进程小,肯定是线程好
```python
# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=0
for i in range(100000000):
res*=i if __name__ == '__main__':
l=[]
print(os.cpu_count()) # 本机为12核
start=time.time()
for i in range(12):
# p=Process(target=work) #耗时8s多
p=Thread(target=work) #耗时44s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start)) # IO密集型
from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
time.sleep(2) if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为12核
start=time.time()
for i in range(400):
p=Process(target=work) #耗时12s多,大部分时间耗费在创建进程上
# p=Thread(target=work) #耗时2s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
2.GIL与自定义互斥锁
不同的数据需要加不同的锁才能保证数据的安全,GIL锁只是对线程加锁,对数据并没有加锁的效果 ```python
from threading import Thread,Lock
import time mutex=Lock()
n=100
def task():
global n
with mutex:
temp=n
time.sleep(0.1)
n=temp-1 if __name__ == '__main__':
l=[]
for i in range(100):
t=Thread(target=task)
l.append(t)
t.start() for t in l:
t.join()
print(n)
# 对于修改不同的数据,需要加不同的锁进行处理
3.死锁与递归锁(了解)
自定义锁一次acquire必须对应一次release,不能连续acquire
递归锁可以连续的acquire,每acquire一次计数加一
from threading import Thread,Lock,RLock
import time # mutexA=Lock()
# mutexB=Lock()
mutexB=mutexA=RLock() class Mythead(Thread):
def run(self):
self.f1()
self.f2() def f1(self):
mutexA.acquire()
print('%s 抢到A锁' %self.name)
mutexB.acquire()
print('%s 抢到B锁' %self.name)
mutexB.release()
mutexA.release() def f2(self):
mutexB.acquire()
print('%s 抢到了B锁' %self.name)
time.sleep(2)
mutexA.acquire()
print('%s 抢到了A锁' %self.name)
mutexA.release()
mutexB.release() if __name__ == '__main__':
for i in range(100):
t=Mythead()
t.start()
4.信号量(了解)
自定义的互斥锁如果是一个厕所,那么信号量就相当于公共厕所,门口挂着多个厕所的钥匙。抢和释放跟互斥锁一致
from threading import Thread,Semaphore
import time
import random
sm = Semaphore(5) # 公共厕所里面有五个坑位,在厕所外面放了五把钥匙 def task(name):
sm.acquire()
print('%s正在蹲坑'%name)
# 模拟蹲坑耗时
time.sleep(random.randint(1,5))
sm.release() if __name__ == '__main__':
for i in range(20):
t = Thread(target=task,args=('伞兵%s号'%i,))
t.start()
5.Event事件
一些线程需要等待另外一些线程运行完毕才能运行,类似于发射信号一样
from threading import Thread,Event
import time
event = Event() # 造了一个红绿灯 def light():
print('红灯亮着的')
time.sleep(3)
print('绿灯亮了')
event.set() def car(name):
print('%s 车正在等红灯'%name)
event.wait()
print('%s 车加油门飙车走了'%name) if __name__ == '__main__':
t = Thread(target=light)
t.start() for i in range(10):
t = Thread(target=car,args=('%s'%i,))
t.start()
6.线程queue
同一个进程下的线程数据都是共享的为什么还要用queue?queue本身自带锁的功能,能够保证数据的安全
# 我们现在的q只能在本地使用,后面我们会学基于网络的q
import queue queue.Queue() #先进先出
q=queue.Queue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get()) queue.LifoQueue() #后进先出->堆栈
q=queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get()) queue.PriorityQueue() #优先级
q=queue.PriorityQueue(3) #优先级,优先级用数字表示,数字越小优先级越高
q.put((10,'a'))
q.put((-1,'b'))
q.put((100,'c'))
print(q.get())
print(q.get())
print(q.get())
并发编程——全局解释器锁GIL的更多相关文章
- (并发编程)全局解释器锁(GIL)-----有了GIL不用给线程加锁了?
一.全局解释器锁 (GIL)运行test.py的流程:a.将python解释器的代码从硬盘读入内存b.将test.py的代码从硬盘读入内存 (一个进程内装有两份代码---一份cpython解释器代码 ...
- python 线程队列、线程池、全局解释器锁GIL
一.线程队列 队列特性:取一个值少一个,只能取一次,没有值的时候会阻塞,队列满了,也会阻塞 queue队列 :使用import queue,用法与进程Queue一样 queue is especial ...
- 全局解释器锁GIL
我们使用高并发,一次是创建1万个线程去修改一个数并打印结果看现象: from threading import Thread import os def func(args): global n n ...
- 全局解释器锁GIL & 线程锁
1.GIL锁(Global Interpreter Lock) Python代码的执行由Python虚拟机(也叫解释器主循环)来控制.Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行 ...
- python 什么是全局解释器锁GIL
什么是全局解释器锁GIL Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在 ...
- 21.线程,全局解释器锁(GIL)
import time from threading import Thread from multiprocessing import Process #计数的方式消耗系统资源 def two_hu ...
- python 多线程编程之使用进程和全局解释器锁GIL
本文主要介绍如何在python中使用线程. 全局解释器锁: python代码的执行是由python虚拟机(又名解释器主循环)进行控制的.python中,主循环中同时只能有一个控制线程在执行,就像单核C ...
- Python核心技术与实战——十九|一起看看Python全局解释器锁GIL
我们在前面的几节课里讲了Python的并发编程的特性,也了解了多线程编程.事实上,Python的多线程有一个非常重要的话题——GIL(Global Interpreter Lock).我们今天就来讲一 ...
- Python全局解释器锁 -- GIL
首先强调背景: 1.GIL是什么?GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定. 2.每个CPU在同一时间只能 ...
随机推荐
- Unicode编码,解释UCS、UTF、BMP、BOM等名词
(转载 谈谈Unicode编码,简要解释UCS.UTF.BMP.BOM等名词 这是一篇程序员写给程序员的趣味读物.所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级 ...
- Project Euler 43 Sub-string divisibility
题意: 1406357289是一个0至9全数字数,因为它由0到9这十个数字排列而成:但除此之外,它还有一个有趣的性质:子串的可整除性.记d1是它的第一个数字,d2是第二个数字,依此类推,我们注意到: ...
- python中的and、or 操作符
在python中 非空 非零的数都为真 1. 其"and"操作符返回的结果是决定表达式结果的值:两边条件都为真则结果为真,有一假则为假 1) 当and两边条件为“真”时,返回的是a ...
- 使用c++Beep实现春节十二响蜂鸣程序
直接编译运行即可 #include<bits/stdc++.h> #include<windows.h> using namespace std; char a[31][71] ...
- 【AIM Tech Round 5 (rated, Div. 1 + Div. 2) 总结】【题解往前或往后翻,不在这】
又是爆炸的一场 心态有点小崩.但问题不大.. 看A题,一直担心有多个正方形..小心翼翼地看完之后,毅然地交上去了. [00:08] A[Accpted] 然后开始看B题. 觉得和之前做的某题很像,但翻 ...
- hdu 3177贪心
#include<stdio.h>/*只能按这种形式排序单纯一种形式是不对的,按ai排序 20 2 1 1 10 20 按bi排序 20 2 5 17 1 16 都是不对的 二a.u+b. ...
- mobile touch 备用
var _scrollIndex=1; function scrollPage(){ var _contentEle = $('.view-container'),_viewEle = _conten ...
- ASP.NET--Razor-model-compare属性用法
学习使用model中的compare属性来判断两个密码之间是否相同 [Required] [StringLength(100, ErrorMessage = "The {0} must be ...
- [SharePoint2010开发入门经典]11、与Office集成
本章概要: 1.创建office集成解决方案使用代码或非代码形式 2.使用内容类型作为能映射到文档库的文档 3.使用InfoPath管理表单 4.使用工作流管理业务流程 5.使用office2010服 ...
- Apache负载均衡与Tomcat集群配置学习(Windows环境)
本文主要参考自http://www.iteye.com/topic/985404?dhcc,经由实际操作配置操并记录而成. 由于最近的一个Java开发项目用到了Tomcat中间件作为web服务器,刚开 ...