day35

一丶GIL锁

什么是GIL锁:

   存在Cpython解释器,全名:全局解释器锁.(解释器级别的锁)

​   GIL是一把互斥锁,将并发运行变成串行.

​   在同一个进程下开启的多个线程,同时只能有一个线程执行,无法利用多核优势

GIL锁的作用:

​   保证同一时间内,共享数据只能被一个任务修改.保证数据的完整性和安全性

​   自动上锁和解锁,不需要人为的添加.减轻开发人员的负担

所谓诟病:单进程的多线程不能利用多核

   通常有人会认为GIL锁不能利用多核处理任务,是Python语言的诟病.个人认为任何一门语言都不是完美的,python问世于20世纪末,当时的CPU也只是单核.

   So,不能利用多核的原因是:同一个进程下,只允许一个线程对共享内容进行修改.不允许多线程同时处理共享数据.

   (打个比方:现在你家有10升(共享数据:10)牛掰的牛奶,你免费送给大家每人1升. 现在有100个人(100个线程)知道了这件事,都上你家来取奶.肯定谁先来,先得. 现在来了10个人(10个线程),每个人都说我去了1升,还剩9升.你真的还剩9升吗? 毛线~~ ,你球都不剩了. 后面来的90个人还能拿到奶吗? 肯定拿拿不到了. So你是不是得上锁,比如你家大门就是一把锁.每次只允许进来(上锁)1个人去奶.取完之后把总的奶量 减一. 第一个取完了出了大门(解锁).剩余的99个人开始抢着进你家门,公平竞争,谁先到你家门,先进就把门锁上了此时发现奶的数量还剩9升,第二个人也只取1升....往后依次延续,当第十一个人进来时,肯定奶已经没了.就表示数据为0.不能再取奶.保证奶的数量的安全性,和完整性(这还是装奶的容器))

GIL抽象图:

   黑色方框就代表GIL锁

二丶验证Cpython的并发效率

需求:

   现在有4个任务(计算密集型任务 或者 IO密集型任务)需要处理.

方案:

   一.开启四个进程

​   二.开启一个进程,四个线程

结果:

   单核:

​      IO密集型:开启进程开销大,进程切换速度远不如线程. 采用一个进程四个线程方案

      计算密集型:没有多核来并行计算,徒增创建进程时间,采用一个进程四个线程方案

   多核:

      IO密集型:尽管多核,开启进程也比较耗时,而且还是要不断的切换.不如线程快.采用一进四线方案

      计算密集型:多核,开启进程并行计算.此时如果用四个线程来会切换回损耗时间.采用四进程方案

多核处理计算密集型:

   多进程的并行执行 单进程的多线程 效率高

# -*-coding:utf-8-*-
# Author:Ds ### 计算密集型
#开启四个进程 , 开启四个线程 from multiprocessing import Process
from threading import Thread
import time
import os def task1():
res=1
for i in range(1,100000000):
res+=i def task2():
res=1
for i in range(1,100000000):
res+=i def task3():
res=1
for i in range(1,100000000):
res+=i def task4():
res=1
for i in range(1,100000000):
res+=i if __name__ == '__main__': start_time=time.time()
### 多核四进程: 处理计算密集型任务,效率高
# 开启四个进程
# p1=Process(target=task1,) # 6.557461261749268
# p2=Process(target=task2,)
# p3=Process(target=task3,)
# p4=Process(target=task4,) ### 虽然本人计算机是多核,但是由于GIL所的原因,同一时刻只允许一个线程处理任务
### 一进程四线程: 处理计算密集型任务,效率低
#开启四个线程
p1=Thread(target=task1,) # 22.048070430755615
p2=Thread(target=task2,)
p3=Thread(target=task3,)
p4=Thread(target=task4,) p1.start()
p2.start()
p3.start()
p4.start() p1.join()
p2.join()
p3.join()
p4.join() print(f'主:{time.time()-start_time}') #### 总结:
#计算密集型: 多进程的并行执行 ~比~ 单进程的多线程 效率高

多核处理IO密集型:

   任务是IO密集型并且任务数量很大,用单进程下的多线程效率高.

from multiprocessing import Process
from threading import Thread
import time
import os def task1():
res=1
time.sleep(3) if __name__ == '__main__': start_time=time.time()
### 并行处理 四核 开启一个进程,使用一个CPU
# 开启进程需要耗费大量时间
# l_t=[]
# for i in range(150):
# ### 多进程处理IO密集型
# p=Process(target=task1) # 耗时: 9.513447999954224
# l_t.append(p)
# p.start()
#
# for j in l_t:
# j.join() ### 并发处理
#虽然是并发处理 ,但是会在CPU之间来回切换.提高效率
l_t = []
for i in range(150):
### 多线程处理IO密集型
p = Thread(target=task1) # 耗时: 3.0212857723236084
l_t.append(p)
p.start() for j in l_t:
j.join() print(f'主:{time.time()-start_time}') #### 总结:
#IO密集型: 任务是IO密集型并且任务数量很大,用单进程下的多线程效率高.

三丶GIL与互斥锁的关系

GIL vs ThreadLock:

​   GIL保护的是解释器级的数据,自动上锁,自动解锁.

   Lock是保护用户自己的数据,手动上锁,手动解锁.如下图:

最新文章

  1. Jenkins 集成打包和上传 App Store 的冲突
  2. C# 获取 mp3文件信息
  3. libevent源码分析:bufferevent
  4. 移动端自动化环境搭建-Appium for Windows的安装
  5. Zendstudio 9.0.2 安装Aptana3 并且配置 jQuery
  6. ssh 文件传输
  7. 【翻译】探究Ext JS 5和Sencha Touch的布局系统
  8. jsp跳转后台代码页的简易方式~
  9. duilib开源界面库
  10. Unity3d 5.x AssetBundle打包与加载
  11. 20162323周楠《Java程序设计与数据结构》第八周总结
  12. python的基本数据类型(一)
  13. 通过锁字符串达到控制并发的效果C#
  14. 【bzoj 4756】[Usaco2017 Jan] Promotion Counting
  15. 绑定的jndi获得connection时,出的错,java.io.NotSerializableException
  16. VDMA时序分析
  17. 【ZooKeeper】ZooKeeper入门流水记
  18. c# 用户页面
  19. iOS 设置UILabel 的内边距
  20. Linux下C连接MySql数据库

热门文章

  1. mysql将多条结果拼接成一条结果
  2. Gradle插件和Gradle对应表
  3. Redis 分布式锁的正确实现方式(Java版)[转]
  4. VLOOKUP使用方法
  5. redis启动警告解决
  6. socks5 代理服务器ss5配置
  7. 对于之前已经push的项目增加.gitignore配置文件不起作用的处理
  8. spark 更改日志输出级别
  9. 实用———springmvc接收参数校验
  10. Feign 自定义编码器、解码器和客户端,Feign 转发请求头(header参数)、Feign输出Info级别日志