• 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('主线程结束')

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

    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函数
    不怕大牛比自己牛,就怕大牛比自己更努力
  • 相关阅读:
    HSF原理
    Spring IOC 容器源码分析
    Spring Bean注册和加载
    CAP和BASE理论
    Java内存模型
    Java线程模型
    IO复用、多进程和多线程三种并发编程模型
    无锁编程本质论
    An Introduction to Lock-Free Programming
    安装与配置ironic
  • 原文地址:https://www.cnblogs.com/zaizai1573/p/10257718.html
Copyright © 2020-2023  润新知