一、线程

1、概念:一条流水线的工作过程

2、和进程的区别和关系

(1)关系

》进程是资源单位,线程是执行单位,cpu真正执行的是线程

》一个进程至少有一个线程

》多线程针对的是一个进程的概念

》从执行的角度说:执行一个进程就相当于开启一个控制(主)线程

》从资源的角度说:开启一个进程就是开辟一个内存空间

(2)区别

》核心1:创建线程开销很小,不用申请空间(比进程快10-100倍);而进程开销大需要申请空间

》核心2:同一进程的多个线程共享该进程的资源和地址空间;但是不同进程的地址空间是隔离的

》线程可以直接访问进程的数据;而子进程是会拷贝父进程的所有数据

》同一进程的多个线程之间可以直接通信;而不同的进程通信则要依靠IPC机制

》线程可以控制同一进程的其它线程;进程只能控制它的子进程

》改变主线程可能贵影响其它线程的行为;改变父进程不会影响子进程

3、和进程的对比

》线程没有“父子”概念

》同一进程的不同线程的进程ID都是一样的

》由于线程共享进程的资源,所以当线程对数据修改时修改的就是该进程内存空间中的数据,但要注意线程和控制线程(该进程)对数据处理的时间先后顺序

二、创建线程

1、代码实现:Thread类(threading模块)

t = Thread(target=函数名,args=(参数,)/kwargs={字典})   实例化

t.start()   发送创建线程请求(由于创建线程开销很小,所以发送请求的同时基本就开启了线程)

t .join()     主线程等待线程结束

from threading import Thread
from multiprocessing import Processdef work(n):print('%s is running' %n)if __name__ == '__main__':t=Thread(target=work,args=(1,))t.start()print('主线程')

2、其它方法:

(1)对象方法

》isAlive() 线程是否存活

》getName()  获取当前线程的名字,默认Thread-1,Thread-2,...这样

》setName()   设置当前线程的名字

(2)模块提供的方法

》currentThread() 获取当前线程对象

》enumerate() 显示当前活跃线程,输出列表

》activeCount()  当前活跃线程的数目

三、守护线程

1、代码实现:

t.daemon=True    必须在start()之前设置

2、概念

》当控制线程(从执行角度上看是该进程)结束守护线程也随之结束

》控制线程只有当所有非守护线程都结束时才算结束

from threading import Thread
import time
def foo():print(123)time.sleep(5)print("end123")def bar():print(456)time.sleep(3)print("end456")if __name__ == '__main__':t1=Thread(target=foo)t2=Thread(target=bar)t1.daemon=Truet1.start()t2.start()print("main-------")

四、GIL:全局解释器互斥锁(不是python的特性)

1、产生背景:在Cpython解释器中特有的,因为python解释器带有数据回收机制,这样就会带来回收和利用的冲突性,所以就要求一个进程的多个线程同一时间只能有一个被执行

2、本质:就是一把互斥锁,实现将并发变为串行,保证数据安全

》》》#1 所有数据都是共享的,这其中,代码作为一种数据也是被所有线程共享的(test.py的所有代码以及Cpython解释器的所有代码)
》》》例如:test.py定义一个函数work,在进程内所有线程都能访问到work的代码,于是我们可以开启三个线程然后target都指向该代码,能访问到意味着就是可以执行。

》》》#2 所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行,即所有的线程要想运行自己的任务,首先需要解决的是能够访问到解释器的代码。

在一个python的进程内,不仅有test.py的主线程或者由该主线程开启的其他线程,还有解释器开启的垃圾回收等解释器级别的线程,总之,所有线程都运行在这一个进程内,毫无疑问

3、实现方式:

with  lock:

    python解释器的代码()

这个lock就是GIL

4、GIL和lock:

》要根据不同的数据来加不同的锁,因为GIL保证不了用户数据的安全,GIL只能保护python解释器级别的数据

》线程要想被执行就要去抢GIL锁(也就是争执行权限)

5、GIL和多线程

》对于多个计算密集型的程序

(1)单核情况下:因为始终只有一个cpu去执行计算,所以就要求开销要小,故选择多线程

(2)多核情况下:因为有多个cpu去执行计算,能够实现真正的并行,效率会很高,而线程每次只有一个在执行没有利用多核的优势,故选择多进程

》对于多个IO密集型程序

(1)单核情况下:因为只有一个cpu执行,需要不断的切换来实现并发,所以要求开销尽量要小,故选择多线程

(2)多核情况下:多个cpu执行的话,遇到IO仍然要阻塞,若是多进程的话就会常常是阻塞状态,运行时间就会是时间最长的哪个程序,而如果是多线程,首先开销很小,其次每次执行一个线程遇到IO阻塞就会立即去处理别的线程,这样效率会提高,故选择多线程

6、为什么要有GIL和代码运行的整个过程

》首先,python解释器带有的数据回收机制,本身是有计数器的,通过计数来判断是否为垃圾数据,而这个计数就是python解释器中的代码提供的功能(其实也是一段程序来实现)也就是python解释器级别的数据,而肯定有可能会出现当python解释器要回收某一个数据而某一个程序正好要使用这个数据的情况,这就带来了冲突,为了解决这种冲突保护数据安全就必须保证同一时间内只能有一个程序来使用python解释器的代码,这就变成了串行,所以就引入了GIL锁的应用

》我们写一段python代码,首先肯定要打开python解释器,这就相当于开启了一个代码解释器的进程,我们在解释器中写代码其实就是用了解释器的功能(也就是通过一段程序实现的功能),而代码本身是不会自己运行的,运行我们所写的代码其实就是开启了另一个进程(即是python解释器进程的子进程)也就是将我们所写的代码作为参数传给python解释器来执行(这其实就是相当于子进程创建时会把父进程(python解释器的代码)的所有数据都拷贝,这样子进程(我们所写的代码)才能运行),而由于GIL锁的存在,每个程序要想运行就要去抢这把锁也就是争取运行权限,争到了就执行若遇到阻塞操作系统就会强制释放掉该程序的运行权限(也就是释放掉GIL锁),这样别的程序再去抢然后运行,等之前的程序处于就绪态时会再去抢GIL锁接着之前的运行状态继续执行,这就是一段代码要想运行起来必须经历的过程

补充一下:

1、开启python解释器操作系统其实是将解释器的代码从硬盘中取出放到内存中去运行,我们所写的代码也是这样的

2、其实进程和线程的创建和开启(个数快慢等,当然线程的开销肯定要比进程小很多),包括程序运行时对GIL锁的争抢和释放以及运行状态的保留等,这些都是由操作系统及电脑性能来控制和决定的,无法由程序本身来操控

》上面说到每个程序运行前要抢GIL锁(运行权限),运行起来时就是按照自己的代码来运行,会产生自己的数据,而这个数据GIL是保护不了的,因为GIL只是锁住了解释器而没有锁住每个进程对同一块数据的处理功能,所以这就是为什么不同的数据要加不同的锁来保护,GIL只是保护python解释器代码级别的数据而已

转载于:https://www.cnblogs.com/wanghl1011/articles/7663035.html

10月13日学习内容整理:线程,创建线程(threading模块),守护线程,GIL(全局解释器互斥锁)...相关推荐

  1. 10月25日学习内容整理:数据操作:增加更新删除,单表查询操作

    >>\G是按行显示,必须是大写 >>插入数据:补充另一种插入记录的方法 -->insert into 表名1(字段1,字段2,...) select 字段1,字段2,.. ...

  2. 9月13日学习内容整理:异常处理

    一.异常处理 1.排错:多行报错的时候,真正报错的是最下面:若报错的地方在别人的代码里,注意别人写的代码是不会报错的,还是找自己的错 2.特点:一旦发生异常,程序不会再向下执行 3.处理方法: (1) ...

  3. 9月11日学习内容整理:正则表达式,re模块

    一.正则表达式:正则是很大的一个知识点,不会仅仅是下面这些东西 1.概念:正则表达式就是一种对字符串匹配的规则,注意是只对字符串,正则表达式和python没啥关系, 2.表达式: (1)字符集:用中括 ...

  4. 1月8日学习内容整理:JS的作用域和作用域链

    补充: 对于编译型语言,是编译一次生成可执行文件来执行多次:对于解释型语言,始终都是编译一次执行一次 python编译时要看有没有赋值操作,没有的话就不编译任何内容:若有赋值操作,才会开辟内存空间,把 ...

  5. 12月7日学习内容整理:ORM单表操作

    补充:url(r"^$")  代表只匹配域名,没有路径部分 一.添加: 1.方式一:昨天讲过的实例化对象 2.方式二: stu_obj=类名(就是表名).objects.creat ...

  6. 3月19日学习内容整理:redis

    1.定义 redis是一个软件,来帮助我们在内存中存储数据,支持持久化 mysql也是一个软件,是帮助我们在硬盘中存储数据 2.应用 由于速度快 可做缓存,存储一些不常改变的数据 临时数据 消息队列 ...

  7. 11月8日学习内容整理:js的引入方式,变量数据类型,运算符,流程控制,函数...

    js是一门成熟的编程语言,专门用浏览器客户端执行的语言 一.js的引入方式 1.直接在body标签中使用script标签写js语言 2.通过script标签导入js文件,<script   sr ...

  8. 9月7日学习内容整理:内置函数

    一.内置函数 1.作用域相关: (1)globals()   查看全局作用域,显示所有的变量 (2)locals()      查看局部作用域,只会显示当前函数使用的变量 2.迭代器相关: (1)it ...

  9. 2月1日学习内容整理:算法

    1.概念 一个计算过程,解决问题的方法 2.时间复杂度和空间复杂度 时间复杂度:用来表示算法的运行效率 >>>一般来说,时间复杂度高的算法比时间复杂度低的算法运行效率高,,但这不是绝 ...

最新文章

  1. numpy matplotlib 柱状图
  2. OpenCASCADE可视化:应用交互服务之交互式上下文
  3. 【Android】Android适配器之ArrayAdapter、SimpleAdapter和BaseAdapter的简单用法
  4. pythonresponse对象的属性_Scrapy中response属性以及内容提取
  5. NodeManager 启动一会儿挂掉
  6. Resources$NotFoundException
  7. 【Vegas原创】红烧肉的做法
  8. [算法]华为笔试题——字母和十进制数映射
  9. 如何使用科来网络分析系统过滤数据包内容
  10. 英雄联盟数据分析专题(一)
  11. 可变条码打印软件如何制作黑底白字条形码
  12. 【CSS手册】css
  13. No such file or directory @ rb_sysopen
  14. 华为emui11系统是鸿蒙系统吗,华为EMUI10.1才更新不久,EMUI11就被曝,网友:咋没见鸿蒙?...
  15. 第十四次CCF CSP认证心得
  16. Nexus Repository Manager 3 远程命令执行漏洞(CVE-2020-10204),CVE-2020-11444 越权漏洞
  17. Solidity语言编辑器REMIX指导大全
  18. java修炼三层境界
  19. 【我,不止于此】TCL电子泛智屏BU研发中心2021届春季校招来袭!
  20. Shortest Path(翻译)

热门文章

  1. 20220129---CTF刷题---WEB--代码审计
  2. idea 无法打开项目_Premiere出现quot;项目看来已经损坏,无法打开”的解决方法...
  3. 初识python 2.x与3.x 区别
  4. hadoop 环境搭建
  5. 为什么企业需要IT资产管理
  6. c++能过,g++过不了
  7. 智能车C车电机传递函数计算
  8. OpenCV中Mat总结
  9. 使用Aspose.Cells组件生成Excel文件实例
  10. C#中DataGridView控件使用大全