线程 定时器 互斥锁

时间:2021-09-29 23:34:41

一、线程的概念。

  线程被称为轻量级的进程。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('\033[42m 连接成功 \033[0m') break
        else: print('\033[43m 连接失败 \033[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()