day9

随着多核时代的到来,怎样充分利用好你的多个CPU的优势成了技术的关注点,那就是多线程多进程编程,二者的区别也很明显,进程是操作系统中拥有资源的最小单位,但是是重量级的。线程是系统调度的最小单位,是轻量级的,一个进程可以拥有很多个线程,但是线程是不拥有资源的,同一个进程中的线程共享这个进程中拥有的资源。以前学习java,一个灰常重要的并发方式就是多线程,因为线程的开销要比进程的少很多,而通过加锁来保证线程安全,进而有线程池来做进一步的优化。

所以前面也花了些时间对python的多线程编程进行了了解,然后又了解了一下python的第三方库线程池threadpool。但是了解后面发现这些都白费了,虽然python提供了thread和threading库来支持多线程的实现,但是python最终还是没办法达到多线程并发的,原因就是GIL。

网上关于GIL的讨论也有很多,我也做了进一步的了解,这里有个例子可以看一下,就是python一个线程的死循环和开启多个线程来执行死循环对于CPU的消耗是差不多的,我的电脑是双核的,来测试一把:

程序运行前cpd的使用率:

开一个线程来执行死循环,主线程也执行死循环cpu的使用率:

一个线程运行死循环程序也是用了50%到60%的cpu,增多一个线程来跑死循环还是用了50%到60%的cpu,都没什么变化。这是为什么呢?原因就是GIL。

1.何方神圣

GIL全称是Global Interpreter Lock,即全局解释锁,每个python解释器都有一个这样的全局锁,在解释器解释执行任何的python代码都要先获得这个锁。所以同一时间只有一个线程持有这个锁在运行,其他的线程都在等待这个锁。所以虽然有两个线程在执行死循环,但实际上每次只有一个线程在运行。

2.要它何用

既然GIL如此的让人蛋疼,以至于多线程都不能发挥多核的优势,那么还要GIL有何用呢。我们只需要像java一样让程序猿自己在访问共享变量处加锁不就可以了吗,为毛一下把整个解释器给锁上了,这不是自找麻烦么。python是解释性语言,是在python解释器上执行的,但是python解释器本身却不是线程安全的,如果没有GIL,那么在多线程中一些简单的操作都会出现问题,在可见变量我们可以自行加锁,而还有很多后台不可见的变量就需要GIL来控制了,比如为了进行垃圾回收而维护的引用计数,如果没有GIL,有可能出现由于线程切换导致的对同一个对象释放两次的情况。所以有了Lock还是需要GIL的。

如果将GIL抛弃,所有的地方都用Lock也可以啊,这样就可以支持多线程并发了,曾有过官方实验发现这样的做法是得不偿失的,单线程的执行效率减慢了将近两倍,而且这样的做法却复杂了N倍,本来一个全局锁就可以解决的问题却花了N多个细微的锁来解决。所以这样是不值得的,何况python还有别的方式来实现并发。

3.有了GIL要Lock何用

既然有了这样一个全局锁来保护了python解释器,让每次只能有一个线程能够得以执行,那么对于共享资源来说,每次也只能有一个线程来访问它,那么python提供的Lock还有用么?就比如这篇博客中第一个例子,不加锁的话结果是不可知的,但是是不会达到一百万的。这又是为什么呢,不是已经有了一个全局锁来保护共享资源吗?

在网上搜到别人的说法是python中线程是对外抽象出来的,而python内部还会想操作系统一样调度这些线程,所以还是需要Lock来保证这些线程间的安全。如果是这样的话倒也说的通,但是python的线程明明是操作系统的原生线程啊。这是为什么呢,这个问题一直困扰着我啊。

4.并发其他途径

多线程是python并发的痛,看来不可能实现的了,但是可以通过其他的途径来实现并发编程,虽然进程较线程是重量级的,但是进程之间是相互独立的,不存在资源共享,所以就没有了互斥的概念,也就不需要锁了,所以还可以通过多进程+协程来实现并发的。

进程并行或者线程并行

各有优缺点,要看情况,不是绝对的,在此不讨论这个,这引出下面两种Python并行处理方法(注释感觉很清晰详细了,不再多说)

0x02    进程处理方法

时间: 2024-12-20 16:16:06

day9的相关文章

Day9 string.characters.count and closures

//                                      **Day9 //                                      CloseSure var arr:[Int] = [1,2,3,4,5,9,8,7,6,0] arr.sort() func compareTwoInts(a:Int,b:Int) -> Bool { return a>b } arr.sort(compareTwoInts) // summary    sorted b

leetcode -day9 Candy & Gas Station & Binary Tree Maximum Path Sum

1.  Candy There are N children standing in a line. Each child is assigned a rating value. You are giving candies to these children subjected to the following requirements: Each child must have at least one candy. Children with a higher rating get m

Day9:yield的表达式形式、面向过程编程(grep -rl 'root' /etc)

一.yield的表达式 def foo(): print('starting') while True: x=yield None#return 2 print('value :',x) g=foo() print(next(g)) print(g.send(2)) 运行结果: starting #运行函数,打印starting后碰到yield停住 None #next()触发后 yield将None赋值给x,打印None后循环碰到yield停住 value : 2 #g.send(2)将2赋值

DAY-9作业

// //  main.m //  DAY- 9作业 // //  Created by lanouhn on 15/1/22. //  Copyright (c) 2015年 lanouhn. All rights reserved. // #import <Foundation/Foundation.h> #import "sort.h" int main(int argc, const char * argv[]) { //    1.输入10个整数,将其中最小的数与

21天战拖记——Day9:“书柜整理法”初步(2014-05-12)

今天复习的强度稍微的降低了一点,由做题转移到了看"理论概念+浏览例题习题+总结技巧"上,今天一定要搞定,睡觉的时候要自己值脑子里面过一遍,这样的话印象更为深刻. 看了一下去年的英语口语考试的资料,自己总结了一些常用的句子.以及作为一个连接者所应用的开头的.结尾的句子还有中间所谓串场的句子. 学习<小强升职记(升级版)>记录: 做事靠系统,不是靠感觉. 大脑不擅长记忆,擅长思考. 衣柜整理法:整理衣柜的五个步骤对英语时间管理的五个流程:捕捉.明确意义.组织整理.深思.行动.该

Alpha冲刺Day9

Alpha冲刺Day9 一:站立式会议 今日安排: 经过为期5天的冲刺,基本完成企业人员模块的开发.因第三方机构与企业存在委托的关系.第三方人员对于风险的自查.风险列表的展示以及自查风险的统计展示(包括折线图和柱状图等图标展示)与企业人员模块存在很多相似性.在有了企业人员模块的基础之上,第三方人员模块开发会显得比较得心应手.计划为期3天进行第三方人员模块的开发. 由黄腾飞继续完成企业自查风险管理,并负责完成分级统计展示模块. 由周静平继续完成风险上报. 由张梨贤协助黄腾飞完成分级统计展示模块的U

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

Java从小白到入门,Day9。JAVAOO-接口

接口:弥补子类继承父类的单一原则,让没有继承关系的类,也能共享行为. Java接口本身没有任何实现,因为Java接口不涉及表象,而只描述public行为,所以Java接口比Java抽象类更抽象化.但接口是接口不是类,不能使用new 运算符实例化一个接口 interface 关键字:用于定义一个接口. 接口: 定义属性: 公共 静态  常量: 语法  public static final 属性名: 定义方法: 公共的,抽象方法; 使用接口:1,让子类去实现接口,implements 关键字,实现

暑假集训day9

今天主要将讲与字符串有关的吧. 1.trie树 Remember the Word(LA_3942) trie树的模板题了.如果trie树不知道可以看蓝书(算法竞赛入门经典第一版)(以下的KMP和AC自动机都可以在此书上看到). #include<cstring> #include<vector> #include<cstdio> #include<iostream> using namespace std; const int mn=400010,mod=

改善程序与设计的55个具体做法 day9

条款23:宁以non-member.non-friend替换member函数 即 以非成员函数 非友元函数 替换成员函数. 直观上,面向对象应该尽可能的封装,封装数据.封装操作等等,所以这个条款可能有悖常理. 比如一个类成员函数CObj::Func(){ Dosomething(); } 该函数会调用其他成员函数做一点微小的工作,想一下把成员函数换成普通函数Func2(const CObj& obj); Func2(const CObj& obj) { obj.Dosomething();