Python中多线程总结

<强> Python中的多线程


<强>多线程


一个进程中有多个线程就是多线程。

一个进程中至少有一个线程,并作为程序的入口,这个就是主线程。一个进程至少有一个主进程,其他线程称为工作线程。


线程安全:线程执行一段代码,不会产生不确定的结果,那这段代码就是线程安全。(例如打印()线程不安全)



<强>线程的守护进程属性


守护进程属性:表示线程是否是守护进程线程,这个值必须在开始()之前设置,否则引发RuntimeError异常

isDaemon():是否是守护进程线程

setDaemon():设置为守护进程线程,必须在开始方法之前设置


线程具有一个守护进程属性,可以设置为真或假,也可以不设置,默认值为没有。如果不设置daemon就取当前的daemon来设置它,主线程是Non-daemon。工作线程不设置daemon属性,则默认是daemon=False .python程序在没有活着的non-daemon线程运行时退出。



join()方法

join(timeout)是线程的标准方法之一。

一个线程中调用里那个一个线程的join方法,调用者将被阻塞,知道盗用线程终止。一个线程可以被join多次。



daemon线程的应用场景

1:后台任务,如发送心跳包、监控,这种场景最多

2:主线程工作才有用的线程,如主线程中维护的公共资源,主线程已经清理了,准备退出,而工作线程使用这些资源工作也没有意义了,一起退出最合适。

3:随时可以被终止的线程


threading.local类

运行时,threading.local实例处在不同的线程中,就从大字典中找到当前线程相关键值对中的字典,覆盖threading.local实例的__dict__。这样就可以在不同的线程中,安全德使用线程独有的数据做到线程间数据隔离,如同本地变量一样安全。


定时器Timer/延迟执行


threading.Timer(interval,function,args=None,Kwargs=None)

start方法执行之后,Timer对象会处于等待状态,等待了interval秒之后,开始执行function函数的。Timer提供了cancel方法,用来取消一个未执行的函数。


Event

是线程间通信机制中最简单的实现,使用一个内部的标记flag,通过flag的True或False的表换来进行操作。

set():标记设置为Ture

clear():标记设置为False

is_set():标记是否为Ture

wait(timeou):设置等待标记为Ture的时长,None为无限等待,等到返回Ture,未等到超时了返回False


Event的wait优于time.sleep,他会更快的切换到其它线程,提高并发效率。


lock


锁,凡是存在共享资源争抢的地方都可以使用锁,从而保证只有一个使用者可以完全使用这个资源。一旦线程获得锁,其他试图获取锁的线程将被阻塞。

acquire(blocking=True,timeout=-1):默认阻塞,阻塞可以设置超时时间,非阻塞时,timeout禁止设置。成功获取锁,返回True,否则返回Flase

release():释放锁,可以从任何线程调用释放。已上锁的多,会被重置未unlocked。未上锁的调用,会派出RuntimeError异常。


加锁、解锁

一般来说,加锁就需要解锁,但加锁后解锁前,还有一些代码执行,就有可能抛出异常,一旦出现异常,锁无法释放,但是当前线程可能因为这个异常被终止了,这就产生了死锁。

加锁、解锁常用的语句:

1:使用try ... funally语句保证锁的释放

2:with上下文管理,锁随想支持上下位管理。


锁的应用:

锁适合用于访问和修改同一个共享资源的时候,即读写同一个资源的时候。

注意事项:

1:少用锁,必要时使用锁,使用了锁,多线程访问被锁的资源时,就成了串行,要么排队执行,要么争抢执行。

2:加锁时间越短越好,不需要就立即释放。

3:一定要避免死锁。


Rlock可重入锁

可重入锁,是线程相关的锁。可在一个线程中获取锁,并可继续在同一个线程中不阻塞获取锁,当锁为释放完,其他线程获取锁就会阻塞。知道当前持有锁的线程释放完锁。



Conditon

构造方法Consition(lock=None),可以传入一个Lock或者Rlock对象,默认是Rlock


Python中多线程总结