Python中多线程总结

发布时间:2019-08-28 09:09:04编辑:auto阅读(1352)

    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.

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

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


关键字

上一篇: 口诀的N种python实现

下一篇: 卸载Python操作