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

线程创建的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('主线程结束')
#####################
1hellowalex主线程结束

查看线程的进程id

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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

多进程效率对比

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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

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

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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函数
posted @ 2022-10-07 20:31  I'm_江河湖海  阅读(6)  评论(0)    收藏  举报