Python中多线程总结
admin
2023-07-18 15:42:00
0次

Python中的多线程


多线程


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

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


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



线程的daemon属性


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

isDaemon():是否是daemon线程

setDaemon():设置为daemon线程,必须在start方法之前设置


线程具有一个daemon属性,可以设置为Ture或False,也可以不设置,默认值为None.如果不设置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


acquire(*args):获取锁

wait(self.timeout=None):等待或超时

notify(n =1):唤醒至多指定数目个数的等待的线程,没有线程等待的线程就没有任何操作

notify_all():唤醒所有等待的线程

condition用于生产者,消费者模型,为了解决生产者消费者速度匹配的问题。由于condition内部使用了锁,最好的方式是使用with上下文。


Barrier

Barrier(parties,action=None,timeout=None):构建Barrier对象,指定参与方数目。timeout是wait方法未指定超时的默认值。

n_waiting:当前在barrier中等待的线程数

parties:资源的个数。

broken:如果broken处于打破的状态,放回True

abort():将将barrier置于broken状态,等待中的线程或者调用等待方法的线程中都会抛出BrokenBarrierError异常,知道reset方法来恢复barrier

reset():恢复barrier,重新开始拦截。


wait方法超时发生,barrier将处于broken状态,知道reset()


semaphore信号量

Semaphore(value=1):构造方法,value小于0,抛ValueError异常

acquite(blocking=True,timeout=None):获取信号量,计数器减1,获取成功返回True

release():释放信号量,计数器加1


semaphore问题

如果遇到release释放次数大于初始值,计数器会增加,超过我们的最大值。

解决方法:

使用Boundedsemaphore类,有界信号量,不允许使用release超出初始值的范围,否则派出ValueError异常。


锁和信号量

锁,只允许同一个时间一个线程独占资源,它是特殊的信号量,即信号量计数器初始值为1.

信号量,可以多个线程访问共享资源,但这个共享资源数量有限。

锁,可以看做特殊的型号量。


相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...