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

线程创建的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=name
def 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 num
num=3
print('子线程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_time
print('线程执行的时间%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 num
tmp=num
tmp-=1
time.sleep(0.01)#模拟
num=tmp
loc.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-1
t1=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函数

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. BZOJ4321queue2——DP/递推

    题目描述 n 个沙茶,被编号 1~n.排完队之后,每个沙茶希望,自己的相邻的两 人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行:  现在想知道,存在多少方案满足沙茶们如此不苛刻的条件. ...

  2. Codeforces Round #545 Div. 1自闭记

    A:求出该行该列各有多少个比其小的取max,该行该列各有多少个比其大的取max,加起来即可. #include<iostream> #include<cstdio> #incl ...

  3. 大学jsp实验3include指令的使用

    1.include指令的使用 (1)编写一个名为includeCopyRight.jsp的页面,页面的浏览效果如下: 要求“2016”这个值可以实现动态更新.请写出页面代码: <%@ page ...

  4. POJ 3322 Bloxorz(算竞进阶习题)

    bfs 标准广搜题,主要是把每一步可能的坐标都先预处理出来,会好写很多 每个状态对应三个限制条件,x坐标.y坐标.lie=0表示直立在(x,y),lie=1表示横着躺,左半边在(x,y),lie=2表 ...

  5. MT【243】球内接四面体体积

    已知半径为2的球面上有$A,B,C,D$四点,若$AB=CD=2$,则四面体$ABCD$的体积最大为____ 解答:利用$V=\dfrac{1}{6}|AB||CD|d<AB,CD>sin ...

  6. 【Luogu2664】树上游戏(点分治)

    [Luogu2664]树上游戏(点分治) 题面 洛谷 题解 很好的一道点分治题. 首先直接点分治,考虑过每个分治重心的链的贡献. 我们从分治重心开始找每种颜色,强制令一种颜色只在其到分治重心的链上第一 ...

  7. Vue中的计算属性与$watch

    计算属性:在模板中绑定表达式是非常便利的,但是他们实际上只用于简单的操作.模板是为了描述视图的结构.在模板中放入太多的逻辑会让模板过重且难以维护.这就是为什么vue.js将绑定表达式限制为一个表达式. ...

  8. php 限制类的对象类型

    事实上,采用哪种处理参数类型的策略,取决于任何潜在bug的严重程度.通常PHP会根据语境自动转换大多数基本数据类型. 因此,你需要在检测类型.转换类型和依赖良好清晰的文档(无论决定用哪一种,都应该提供 ...

  9. js原生事件系统与坐标系统

    今天来实现一个可兼容的js原生拖拽,在这里面我将会讲到: 1.封装兼容性的事件系统. 2.封装得到鼠标当前位置的系统. 3.完成拖拽的实现. 首先,我们要讲到鼠标位置的获取,讲到这个,就离不开js的w ...

  10. LOJ#2541 猎人杀

    解:step1:猎人死了之后不下台,而是继续开枪,这样分母不变...... 然后容斥,枚举猎人集合s,钦定他们在1之后死.定义打到1的时候结束,枚举游戏在i轮时结束. 发现式子是一个1 + x + x ...