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

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

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

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

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

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

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

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

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

守护线程:

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

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

GIL锁:

  

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

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

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

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

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

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

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

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

1
hellowalex
主线程结束

###查看线程的进程id

  1. import os
  2. from threading import Thread
  3. def f1(n):
  4. print('1号',os.getpid())
  5. print('%s号'%n)
  6. def f2(n):
  7. print('2号',os.getpid())
  8. print('%s'%n)
  9. if __name__ == '__main__':
  10. t1=Thread(target=f1,args=(1,))
  11. t2=Thread(target=f2,args=(2,))
  12. t1.start()
  13. t2.start()
  14. print('主进程id',os.getpid())
  15. ############
  16. 线程ID是一样的

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

  1. import os
  2. import time
  3. from threading import Thread
  4. num=100
  5. def f1(n):
  6. global num
  7. num=3
  8. print('子线程num',num)
  9. if __name__ == '__main__':
  10. t=Thread(target=f1,args=(1,))
  11. t.start()
  12. t.join()#主进程等待子进程运行完才继续执行
  13. print('主进程的num',num)
    ###################

子线程num 3
主进程的num 3

###多进程效率对比

  1. import time
  2. from threading import Thread
  3. from multiprocessing import Process
  4. def f1():
  5. for i in range(5):
  6. i=i+i
  7. if __name__ == '__main__':
  8. t_s_time=time.time()
  9. t_list=[]
  10. # 查看一下20个线程执行20个任务的执行时间
  11. for i in range(20):
  12. t=Thread(target=f1,)
  13. t.start()
  14. t_list.append(t)
  15. [tt.join() for tt in t_list]
  16. t_e_time=time.time()
  17. t_dif_time=t_e_time-t_s_time
  18. # print(t_dif_time)
  19. #查看一个20个进程执行的任务时间
  20. ##########################################
  21. p_s_time=time.time()
  22. p_list=[]
  23. for i in range(20):
  24. p=Process(target=f1,)
  25. p.start()
  26. p_list.append(p)
  27. [pp for pp in p_list]
  28. p_e_time=time.time()
  29. p_dif_time=p_e_time-p_s_time
  30. print('线程执行的时间%s'%t_dif_time)
  31. print('进程执行的时间%s' % p_dif_time)
  32. ###################
  33. 线程执行的时间0.003000497817993164
  34. 进程执行的时间0.2560145854949951

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

  1. import time
  2. from multiprocessing import Process
  3. from threading import Thread,Lock
  4. num=100
  5. def f1(loc):
  6. loc.acquire()#没加锁的时候 多个程序会抢一个数据 造成数据不安全
  7. global num
  8. tmp=num
  9. tmp-=1
  10. time.sleep(0.01)#模拟
  11. num=tmp
  12. loc.release()
  13. if __name__ == '__main__':
  14. t_loc=Lock()
  15. t_list=[]
  16. for i in range(10):
  17. t=Thread(target=f1,args=(t_loc,))
  18. t.start()
  19. t_list.append(t)
  20. [tt.join() for tt in t_list]
  21. print('主进程',num)
  22. ##############
  23. 主进程 90

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

  1. import time
  2. from threading import Thread,Lock,RLock
  3. def f1(locA,locB):
  4. locA.acquire()
  5. print('f1>>1号抢到了A锁')
  6. time.sleep(1)
  7. locB.acquire()
  8. print('f1>>1号抢到了B锁')
  9. locB.release()
  10. locA.release()
  11. def f2(locA,locB):
  12. locB.acquire()
  13. print('f2>>2号抢到了B锁')
  14. locA.acquire()
  15. time.sleep(1)
  16. print('f2>>2号抢到了A锁')
  17. locA.release()
  18. locB.release()
  19. if __name__ == '__main__':
  20. locA = Lock()
  21. locB = Lock()
  22. t1 = Thread(target=f1,args=(locA,locB))
  23. t2 = Thread(target=f2,args=(locA,locB))
  24. t1.start()
  25. t2.start()
  26. ##################
  27. f1>>1号抢到了A
  28. f2>>2号抢到了B

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

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

  1. import time
  2. from threading import Thread,Lock,RLock
  3. def f1(LocA,LocB):
  4. # time.sleep(1)
  5. LocA.acquire()
  6. print('f1>>1号抢到a锁')
  7. time.sleep(1)
  8. LocB.acquire()
  9. print('f1>>1号抢到b锁')
  10. LocB.release()
  11. LocA.release()
  12. def f2(LocA, LocB):
  13. # time.sleep(1)
  14. LocB.acquire()
  15. print('f2>>2号抢到b锁')
  16. time.sleep(1)
  17. LocA.acquire()
  18. print('f2>>2号抢到a锁')
  19. LocA.release()
  20. LocB.release()
  21. if __name__ == '__main__':
  22. LockA=Lock()
  23. LockB=Lock()
  24. LockA=LockB=RLock()#递归锁,维护一个计时器,acquire+1 release-1
  25. t1=Thread(target=f1,args=(LockA,LockB))
  26. t2=Thread(target=f2,args=(LockA,LockB))
  27. t1.start()
  28. t2.start()
  29. #######################
  30. f1>>1号抢到a
  31. f1>>1号抢到b
  32. f2>>2号抢到b
  33. f2>>2号抢到a

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

  1. import time
  2. from threading import Thread
  3. def f1():
  4. time.sleep(3)
  5. print('xxxxxx')
  6. def f2():
  7. time.sleep(2)
  8. print('普通子进程的代码')
  9. if __name__ == '__main__':
  10. p=Process(target=f1,)
  11. p.daemon=True
  12. # 等待所有非守护线程结束才结束
  13. p.start()
  14.  
  15. p2=Process(target=f2,)
  16. p2.start()
  17. p2.join()
  18. print('主进程,结束')
  19. ####################
  20. 普通子进程的代码
  21. 主进程,结束
    如果把 上面的 f2 改成3s f1改成2s 会打印出xxxx 因为f2执行时间大于f1函数

python 线程(创建2种方式,锁,死锁,递归锁,GIL锁,守护进程)的更多相关文章

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

    代码创建进程和线程的两种方式 """ 定心丸:Python创建进程和线程的方式基本都是一致的,包括其中的调用方法等,学会一个 另一个自然也就会了. "" ...

  2. Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池

    Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...

  3. 0036 Java学习笔记-多线程-创建线程的三种方式

    创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...

  4. 并发编程8 线程的创建&验证线程之间数据共享&守护线程&线程进程效率对比&锁(死锁/递归锁)

    1.线程理论以及线程的两种创建方法 2.线程之间是数据共享的与join方法 3.多线程和多进程的效率对比 4.数据共享的补充线程开启太快 5.线程锁 互斥锁 同步锁 6.死锁现象和递归锁 7.守护线程 ...

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

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

  6. Java创建线程的第二种方式:实现runable接口

    /*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法    将线程要运行的代码存放在 ...

  7. 创建线程的两种方式比较Thread VS Runnable

    1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...

  8. Java中创建线程的两种方式

    创建线程的第一种方式: 创建一个类继承Thread 重写Thread中的run方法 (创建线程是为了执行任务 任务代码必须有存储位置,run方法就是任务代码的存储位置.) 创建子类对象,其实就是在创建 ...

  9. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

随机推荐

  1. BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd

    题目描述 在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出 ...

  2. 第四十九天 mysql 索引 元类

    一 昨日回顾 视图 触发器 事务 什么是事务 逻辑上的一组操作 要么都成功 要么都失败 如何使用 start transaction 开启事务 mysql 默认一条sql就是一个事务 pymysql默 ...

  3. Matplotlib学习---用matplotlib画面积图(area chart)

    这里利用Nathan Yau所著的<鲜活的数据:数据可视化指南>一书中的数据,学习画图. 数据地址:http://book.flowingdata.com/ch05/data/us-pop ...

  4. CCF WC2017 & THU WC2017 旅游记

    day-x 真·旅游 去了杭州的一些景点,打了几场练习赛. day0 报到日 领资料.入住,中午在食堂吃饭,感觉做的挺好的,和二高食堂差不多.晚上还有开幕式. day1~day4 白天讲课,晚上营员交 ...

  5. new Date()导致日期增加了一天

    问题是:将字符串 "Sun Nov 12 14:00:00 CST 2017"  转成Date类型 有一个简单的方法是直接使用new Date(),但是这个方法对于某些日期的计算, ...

  6. 【BZOJ5308】[ZJOI2018]胖(模拟,ST表,二分)

    [BZOJ5308][ZJOI2018]胖(模拟,ST表,二分) 题面 BZOJ 洛谷 题解 首先发现每条\(0\)出发的边都一定会更新到底下的一段区间的点. 考虑存在一条\(0\rightarrow ...

  7. js 触摸的Event--获取触摸位置

    继上一篇js原生拖拽之后,现在又来写一下移动端touch列表,获取触摸位置.pc端的event事件,鼠标的位置信息在上一篇,点此进入上一篇. touch有3个事件:touchstart,touchmo ...

  8. 关于react-native项目在MacBookPro环境下打包成IPA

    苹果开发者打包是需要接入公司的开发者账户里面的.看是企业账户还是什么,具体我不太清楚. 不过打包的方法倒是大同小异. 我们一起新建项目,先跑起来这个项目 npm install -g yarn rea ...

  9. react-native实现电影列表

    页面运行效果 代码: import React, { Component } from "react"; import { Image, FlatList, StyleSheet, ...

  10. http 请求头和响应头

    客户端发送请求过程带着的数据: 1.请求地址 2.请求方式 3.请求头 request headers 4.请求参数 https://www.juhe.cn/ 130.... 1a2b....pei ...