• 线程 定时器 互斥锁


    一、线程的概念。

      线程被称为轻量级的进程。GIL:全局解释锁(只有CPython解释器才有)

      对于线程来说因为有了GIL所以没有真正的并行。

      计算机的执行单位以线程为单位。计算机的最小可执行单位为线程。

      进程是资源分配的基本单位。线程是可执行的基本单位,是可被调度的基本单位。

      线程不可以自己独立拥有资源。线程的执行,必须依赖于所属进程中的资源。

      进程中必须至少应该有一个线程。

      线程又分为用户级线程和内核级线程(了解)

      线程的组成:

        代码段、数据段、线程控制块(TCB)

    二、线程和进程的比较

      1、cpu切换线程要比cpu切换进程快很多

        在python中,如果IO操作比较多的话,使用线程最好。计算密集用多进程。

    # 进程和线程在同时调用多个时,时间效率上有很大的差距
    om threading import Thread
    from multiprocessing import Process
    import time
    
    def func():
        pass
    
    if __name__ == '__main__':
        s = time.time()
        for i in range(1000):
            p = Process(target=func)
            p.start()
        print('进程:',time.time() - s)
    
        s1 = time.time()
        for i in range(1000):
            t = Thread(target=func)
            t.start()
        print('进程:', time.time() - s1)

      2、在同一个进程内,所有线程共享该进程的pid,也就是说所有线程共享所属进程的所有资源和内存地址。

      3、在同一个进程内,所有线程共享该进程中的全局变量

      4、因为GIL锁的存在,在cpython中,没有真正的线程并行。但是有真正的多进程并行。

      5、关于守护进程和守护线程(代码执行结束并不代表程序结束)

        守护进程:根据父进程的代码执行结束而结束。

        守护线程:根据父线程的执行结束而结束。

    # 进程和线程不能同时执行要分别执行才有效果
    from threading import Thread
    from multiprocessing import Process
    import time
    
    def daemon_():
        time.sleep(1)
        print('守护线程')
    def func():
        time.sleep(3)
        print('普通子线程')
    if __name__ == '__main__':
        t = Thread(target=func,args=())
        t1 = Thread(target=daemon_,args=())
        t.start()
        t1.daemon = True
        t1.start()
        # time.sleep(2)
        print(666)
    
    # 守护线程是根据主线程执行结束才结束
    # 守护线程不是根据主线程的代码执行结束而结束
    # 主线程会等待普通线程执行结束,再结束
    # 守护线程会等待主线程结束,再结束
    # 所以,一般把不重要的事情设置为守护线程
    # 守护进程是根据主进程的代码执行完毕,守护进程就结束
    
    def daemon1_():
        time.sleep(1)
        print('守护进程')
    def func1():
        time.sleep(2)
        print('普通子进程')
    if __name__ == '__main__':
        p = Process(target=func1,args=())
        p1 = Process(target=daemon1_,args=())
        p1.daemon = True
        p1.start()
        p.start()
        print(999)

    三、线程的使用

      1、锁机制

        递归锁

          RLock()      可以有  无止尽的锁,但是有一把万能钥匙

    from threading import RLock
    
    l = RLock()
    l.acquire()
    l.acquire()
    l.acquire()
    l.acquire()
    print(123) # 不需要去解锁

        互斥锁

          Lock()       一把锁配一把钥匙

    # 用Lock实现互斥锁
    from threading import Lock
    
    
    l = Lock()
    l.acquire()
    print('123')
    l.acquire() # 会造成死锁 一直处于等待状态
    l.release()
    print('456')

        GIL:全局解释锁

          锁的是线程,是cpython解释器上的一个锁,意思是在同一时间只允许一个线程访问cpu

      2、信号量:

        from threading import Semaphore   和进程类似

    from threading import Thread,Semaphore,Lock
    
    
    def func(l,i):
        l.acquire() # 5个人可以同时打开这把锁
        print('第%s个'% i)
        l.release() # 5个人可以同时离开并锁上锁
    
    if __name__ == '__main__':
        sem = Semaphore(5) # 一把锁配了5把钥匙
        for i in range(5):
            t = Thread(target=func,args=(sem,i))
            t.start()

      3、事件:

        from threading import Event   和进程类似

    rom threading import Event,Thread
    import time,random
    
    
    def conn_mysql(e,i):
        c = 1
        while c <= 3:
            if e.is_set():
                print('33[42m 连接成功 33[0m')
                break
            else:
                print('33[43m 连接失败 33[0m')
            e.wait(0.5)
            c += 1
    def check_mysql(e):
        print('数据库正在连接。。。。')
        time.sleep(random.randint(1,2))
        e.set()
    
    if __name__ == '__main__':
        e = Event()
        t_check = Thread(target=check_mysql,args=(e,))
        t_check.start()
        for i in range(10):
            t_conn = Thread(target=conn_mysql, args=(e,i))
            t_conn.start()

      4、条件

        from threading import Condition

        条件是让程序员自行去调度线程的一个机制

        Condition  涉及4个方法

          acquire()

          release()

          wait()   是指让线程阻塞住

          notify(int)   是指给wait发一个信号,让wait变成不阻塞

              int是指,你要给wait发的信号是多少

    from threading import Thread,Condition
    
    def func(i,con):
        con.acquire()
        con.wait() # 线程执行到这里会阻塞,等待notify发送信号,来唤醒这批线程。
        con.release()
        print('第%s个执行'% i)
    
    if __name__ == '__main__':
        con = Condition() # 实例化
        while 1:
            for i in range(10):
                t = Thread(target=func, args=(i, con))
                t.start()
            num = int(input('>>>'))
            con.acquire()
            con.notify(num) # 发送一个信号给num个正阻塞在wait的线程,让这些线程正常执行。
            con.release()

      5、定时器

        from threading import Timer

          Timer(time,func)

          time:睡眠的时间,以秒为单位

          func:睡眠之后,需要执行的任务

    from threading import Timer
    
    def func():
        print('123')
    
    if __name__ == '__main__':
        t = Timer(3,func) # 意思为3秒以后执行func函数
        t.start()

      

      

  • 相关阅读:
    Java 抽象类
    7.队列的链表实现
    6.队列的数组实现
    5.栈的链表实现
    4.栈的数组实现
    3.线性表-cursor
    2.线性表-Linked list
    1.线性表-Array
    hello world!
    boost 大小端转换
  • 原文地址:https://www.cnblogs.com/wjs521/p/9526525.html
Copyright © 2020-2023  润新知