###############总结############

线程创建的2种方式(重点)

进程:资源分配单位    线程:cpu执行单位(实体)

线程的创建和销毁的开销特别小

线程之间资源共享,是同一个进程中的资源共享,会涉及到安全问题,所以需要加锁解决

:牺牲了效率,保证了数据安全(重点)

死锁现象:出现在嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待(重点)

递归锁: 解决了死锁现象(重点)

  rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire+1,release就-1,当计数器为0的时候,大家才会抢这个锁

守护线程:

  守护线程:等待所有非守护线程结束才结束

  守护进程: 主进程运行代码结束,守护进程会随之结束

GIL锁:

  

运行一个py文件 需要开辟一块内存,内存中有 cpython解释器,py文件代码

cpython解释器有 编译器和虚拟机 编译器:编译出来后是c语言的字节码

              经过虚拟机后:变成可执行的二进制文件 到cpu里面执行

py文件代码到cpython解释器的时候,会经过一个gil锁,这个锁会把文件中的多个线程变成并行处理的方式

这样的话 一次只能出一个二进制文件导致单核cpu执行,没法做到多线程

如果做到同时处理多核计算形任务了?

使用多进程运用进程运用多核技术,因为每个进程里面都有cpython解释器程序

一个普通的cpu 一秒可以随便执行500万条mps 也就是5亿条指令如果你的程序是I/O型的(一般你的程序都是这个)(input、访问网址网络延迟、打开/关闭文件读写),在什么情况下用的到高并发呢(金融计算会用到,人工智能(阿尔法狗),但是一般的业务场景用不到,爬网页,多用户网站、聊天软件、处理文件)I/O型的操作很少占用CPU
###第一种from threading import Thread
def f1(n):print(n)
if __name__ == '__main__':t1=Thread(target=f1,args=(1,))t1.start()
###第二种
class mythread(Thread):def __init__(self,name):super().__init__()self.name=namedef run(self):print('hellow'+self.name)
if __name__ == '__main__':t=mythread('alex')t.start()print('主线程结束')

#####################

1
hellowalex
主线程结束

###查看线程的进程id

import os
from  threading import Thread
def f1(n):print('1号',os.getpid())print('%s号'%n)
def f2(n):print('2号',os.getpid())print('%s'%n)
if __name__ == '__main__':t1=Thread(target=f1,args=(1,))t2=Thread(target=f2,args=(2,))t1.start()t2.start()print('主进程id',os.getpid())
############
线程ID是一样的

###验证线程是数据共享的

import os
import time
from threading import Thread
num=100
def f1(n):global numnum=3print('子线程num',num)
if __name__ == '__main__':t=Thread(target=f1,args=(1,))t.start()t.join()#主进程等待子进程运行完才继续执行print('主进程的num',num)###################

子线程num 3
主进程的num 3

###多进程效率对比

import time
from threading import Thread
from multiprocessing import Process
def f1():for i in range(5):i=i+i
if __name__ == '__main__':t_s_time=time.time()t_list=[]# 查看一下20个线程执行20个任务的执行时间for i in range(20):t=Thread(target=f1,)t.start()t_list.append(t)[tt.join() for tt in t_list]t_e_time=time.time()t_dif_time=t_e_time-t_s_time# print(t_dif_time)#查看一个20个进程执行的任务时间
##########################################p_s_time=time.time()p_list=[]for i in range(20):p=Process(target=f1,)p.start()p_list.append(p)[pp for pp in p_list]p_e_time=time.time()p_dif_time=p_e_time-p_s_timeprint('线程执行的时间%s'%t_dif_time)print('进程执行的时间%s' % p_dif_time)
###################
线程执行的时间0.003000497817993164
进程执行的时间0.2560145854949951

####锁 牺牲了效率,保证了数据安全(重点)

import time
from multiprocessing import Process
from threading import Thread,Lock
num=100
def f1(loc):loc.acquire()#没加锁的时候 多个程序会抢一个数据 造成数据不安全global numtmp=numtmp-=1time.sleep(0.01)#模拟num=tmploc.release()
if __name__ == '__main__':t_loc=Lock()t_list=[]for i in range(10):t=Thread(target=f1,args=(t_loc,))t.start()t_list.append(t)[tt.join() for tt in t_list]print('主进程',num)
##############
主进程 90

#####死锁现象 出现在嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待(重点)

import time
from threading import Thread,Lock,RLock
def f1(locA,locB):locA.acquire()print('f1>>1号抢到了A锁')time.sleep(1)locB.acquire()print('f1>>1号抢到了B锁')locB.release()locA.release()
def f2(locA,locB):locB.acquire()print('f2>>2号抢到了B锁')locA.acquire()time.sleep(1)print('f2>>2号抢到了A锁')locA.release()locB.release()
if __name__ == '__main__':locA = Lock()locB = Lock()t1 = Thread(target=f1,args=(locA,locB))t2 = Thread(target=f2,args=(locA,locB))t1.start()t2.start()
##################
f1>>1号抢到了A锁
f2>>2号抢到了B锁

递归锁: 解决了死锁现象(重点)

  rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire+1,release就-1,当计数器为0的时候,大家才会抢这个锁

import time
from threading import Thread,Lock,RLock
def f1(LocA,LocB):# time.sleep(1)
    LocA.acquire()print('f1>>1号抢到a锁')time.sleep(1)LocB.acquire()print('f1>>1号抢到b锁')LocB.release()LocA.release()
def f2(LocA, LocB):# time.sleep(1)
    LocB.acquire()print('f2>>2号抢到b锁')time.sleep(1)LocA.acquire()print('f2>>2号抢到a锁')LocA.release()LocB.release()
if __name__ == '__main__':LockA=Lock()LockB=Lock()LockA=LockB=RLock()#递归锁,维护一个计时器,acquire+1 release-1t1=Thread(target=f1,args=(LockA,LockB))t2=Thread(target=f2,args=(LockA,LockB))t1.start()t2.start()
#######################
f1>>1号抢到a锁
f1>>1号抢到b锁
f2>>2号抢到b锁
f2>>2号抢到a锁

守护线程: 等待所有非守护线程结束才结束

import time
from threading import Thread
def f1():time.sleep(3)print('xxxxxx')
def f2():time.sleep(2)print('普通子进程的代码')
if __name__ == '__main__':p=Process(target=f1,)p.daemon=True# 等待所有非守护线程结束才结束
    p.start()p2=Process(target=f2,)p2.start()p2.join()print('主进程,结束')
####################
普通子进程的代码
主进程,结束如果把 上面的 f2 改成3s f1改成2s 会打印出xxxx 因为f2执行时间大于f1函数

转载于:https://www.cnblogs.com/zaizai1573/p/10257718.html

python 线程(创建2种方式,锁,死锁,递归锁,GIL锁,守护进程)相关推荐

  1. python创建多线程_Python 多线程,threading模块,创建子线程的两种方式示例

    本文实例讲述了Python 多线程,threading模块,创建子线程的两种方式.分享给大家供大家参考,具体如下: GIL(全局解释器锁)是C语言版本的Python解释器中专有的,GIL的存在让多线程 ...

  2. java 多线程编程(包括创建线程的三种方式、线程的生命周期、线程的调度策略、线程同步、线程通信、线程池、死锁等)

    1 多线程的基础知识 1.1 单核CPU和多核CPU 单核CPU,其实是一种假的多线程,因为在一个时间单元内,也只能执行一个线程的任务.微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那 ...

  3. Python创建进程、线程的两种方式

    代码创建进程和线程的两种方式 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多已经做案例的人,却不知道如何去学习更加高深的知识. ...

  4. 创建线程的三种方式、线程运行原理、常见方法、线程状态

    文章目录 1.创建线程的三种方式 1.1 继承Thread类并重写run方法 1.2 使用Runnable配合Thread 1.3 通过Callable和FutureTask创建线程 2.Runnab ...

  5. 创建线程的几种方式?JSP的九大内置对象及作用分别是什么?servlet的生命周期及常用方法?转发和重定向区别?ajax书写方式及内部主要参数都有哪些

    文章目录 1 , 创建线程的几种方式? 问题扩展: 2 ,JSP的九大内置对象及作用分别是什么? (1) 问题分析: (2) 核心答案讲解: 1.request对象 2.response对象 3.se ...

  6. 【并发编程】创建线程的四种方式

    上一篇我们初步认识了线程,现在我们来讲一下,创建线程的三种方式 1.继承Thread 类通过继承thread类,然后重写run方法(run方法中是线程真正执行的代码,runable也是如此)即可.当子 ...

  7. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  8. java 创建线程_【80期】说出Java创建线程的三种方式及对比

    点击上方"Java面试题精选",关注公众号 面试刷图,查缺补漏 >>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅. 一.Ja ...

  9. 【并发技术01】传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承 Thread 类,并重写 run() 方法:二是实现 Runnable 接口,覆盖接口中的 run() 方法,并把 Runnable 接口的实现扔给 T ...

  10. Python 35 线程(1)线程理论、开启线程的两种方式

    一:线程理论 1 什么是线程 进程其实一个资源单位,而进程内的线程才是cpu上的执行单位 线程其实指的就是代码的执行过程 2 为何要用线程    线程vs进程      1. 同一进程下的多个线程共享 ...

最新文章

  1. Interview:算法岗位面试—11.15下午上海某航天***公司(国企)技术面之工业机器视觉认知、计算机视觉算法的理解、目标检测相关项目案例
  2. python123说句心里话的题_如何与回避型依恋的人谈恋爱?
  3. python安装tensorflow报错_Anaconda安装tensorflow报错问题解决方法
  4. Error: GlobalConfigUtils setMetaData Fail
  5. sql backup database备份d盘_Oracle-备份与恢复(二)RMAN备份-自动备份计划任务脚本...
  6. 从mediaserver入手快速理解binder机制(最简单理解binder)
  7. layerdate时间插件不允许选着部分置灰效果处理
  8. 哪些人需要发表期刊论文
  9. 使用反射时出现java.lang.NoSuchMethodException
  10. sm4加密和sm3加密
  11. win7与深度(Deepin)linux 双系统启动顺序调整
  12. 如何提高mysql插入速度_mysql技巧:提高插入数据(添加记录)的速度
  13. Go语言自学系列 | golang标准库os模块 - File文件读操作
  14. 汉与匈奴之战,中华民族兴起的序幕
  15. Javaweb-请求报500问题
  16. NTFS - 获取NTFS系统格式的盘符
  17. 【JAVA】PAT 乙级 1025 反转链表(测试点5超时,牛客网通过)
  18. .native的使用
  19. 通过js给input框的value赋值触发input事件
  20. 一元函数中的导数、微分和不定积分的关系

热门文章

  1. AES-128\192\256加密算法及其安全脆弱分析
  2. 推荐系统开源软件汇总和评点
  3. 2021-08-13servlet 原理及注意事项
  4. 2021-06-27函数定义与参数
  5. 2021-06-18html基本标签学习
  6. 区块链 Solidity中uint转string 数字转字符串
  7. 制造跨度 makespan是什么
  8. Kubernetes 小白学习笔记(4)--kubernetes是什么
  9. Ubuntu16.04 安装Apache2和php后,无法访问phpinfo.php
  10. mysql odbc 驱动程序不支持所需的属性_ODBC 驱动程序不支持所需的属性。