pythonの多线程

python的GIL

在非python环境中,单核情况下,同时只能有一个任务执行。多核时可以支持多个线程同时执行。

在python中,无论有多少核,同时只能执行一个线程,这是由于GIL所导致的。

GIL(Global Interpreter Lock全局解释器锁),是为了数据安全所做的决定,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”。

在一个python进程中,GIL只有一个

拿不到GIL的线程,就不允许进入CPU执行

GIL的释放逻辑

python2.x中,在线程遇见IO操作或者ticks计数达到100时进行释放(ticks是python自身的一个计数器,专门用于做GIL,每次释放后归零,这个计数可以通过sys.setcheckinterval来调整)

python3.x中,改为使用计时器(当执行时间达到阈值后,当前线程释放GIL)

释放GIL锁后,线程会进行锁竞争,随后切换线程,会消耗资源

由于python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行),所以在多核CPU上,python的多线程效率并不高

python多线程工作过程

1.拿到公共数据

2.申请GIL

3.python解释器调用os原生线程

4.os操作cpu执行运算

5.当该线程达到gil的释放要求时,无论运算是否已经执行完,gil都被要求释放

6.其他线程重复上面的过程

7.轮到之前的线程时,又会切换到之前的线程(从它记录的上下文继续执行)

整个过程是每个线程执行自己的运算,当执行时间到,就进行切换。

Python多线程中的数据锁

互斥锁Lock

       互斥锁的好处就是确保了某段关键代码只能由一个线程从头到尾完整地执行

递归锁RLock

       RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。

信号量Semaphore

       信号量Semaphore本质也是一把锁,但是这把锁可以限定允许多个任务同时执行任务,但是不能超出规定的限制,如(Semaphore(5))参数5就代表可以执行5个任务,如果第6个任务要执行,必须等5个任务中的一个结束,然后第六个才能进入执行。

python多线程中的线程同步

条件Condition

       可以把Condiftion理解为一把高级的琐,允许我们能够控制复杂的线程同步问题。

     wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。

       notify()、notify_all()、notifyAll()会唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

事件Event

       事件处理的机制:全局定义了一个“Flag”,当flag值为“False”,那么event.wait()就会阻塞,当flag值为“True”,那么event.wait()便不再阻塞。

       用于某线程控制其他线程的执行

队列Queue

       主要有队列queue、堆栈queue、优先级queue三种

python多线程中的守护进程

当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行。

守护进程可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止。

如果要避免上面的情况,就要使用join(),join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止

python多线程中的ThreadLocal

一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。

原理:{thread_id:{k1:v1}, ... }

可以理解为全局变量local_school是一个dict,不但可以用local_school.student,还可以绑定其他变量,如local_school.teacher等等。

ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

python多线程中的其他常用工具

定时器Timer

       定时器,指定n秒后执行某操作,注:是与当前线程异步的

 

线程池

 

       系统处理任务时,需要为每个请求创建和销毁对象。当有大量并发任务需要处理时,再使用传统的多线程就会造成大量的资源创建销毁导致服务器效率的下降。这时候,线程池就派上用场了。线程池技术为线程创建、销毁的开销问题和系统资源不足问题提供了很好的解决方案。

 

       使用见参考资料

 

python多线程的demo

https://github.com/HanChengITer/PyStudy/blob/master/parallel_tasks/transportation_threads.py

参考资料

Python3之多线程GIL、同步锁、信号量、死锁与递归锁、线程Queue、Event、定时器

https://blog.csdn.net/qq_33733970/article/details/77719427

python中lock和rlock(递归锁)的区别、condition

https://www.aliyun.com/jiaocheng/463803.html

Python3线程间通信

https://blog.csdn.net/weixin_38125866/article/details/76796655

线程池python

https://www.cnblogs.com/tracylining/p/3471594.html

posted @ 2018-06-21 21:17  yc紫日  阅读(182)  评论(0编辑  收藏  举报