leoatchina的博客

python_thread_sync

前言

Python的代码的执行是由Python虚拟机(又名解释器主循环)进行控制的。Python在设计时就是这样考虑的,在主循环中同时只能有一个控制线程在执行,就像单核CPU系统中的多进程一样。内存中可以有许多程序,但是在任意给定时刻只能有一个程序在运行。同理,尽管Python解释器中可以运行多个线程,但是在任意给定时刻只有一个线程会被解释器执行。
对Python虚拟机的访问是由全局解释锁(GIL)控制的。这个锁就是用来保证同时只能有一个线程运行的。在多线程环境中,Python虚拟机将按下面所述的方式执行。

  1. 设置GIL。
  2. 切换进一个线程去运行。
  3. 执行下面操作之一。
    • 指定数量的字节码指令
    • 线程主动让出控制权
  4. 把线程设置回睡眠状态
  5. 解锁GIL
  6. 重复上述步骤

在讨论普通的GIL之前,有一点要强调的是GIL只会影响到那些严重依赖CPU的程序(比如计算型的)。 如果你的程序大部分只会设计到I/O,比如网络交互,那么使用多线程就很合适, 因为它们大部分时间都在等待。
对于CPU依赖型的程序,你要搞清楚计算的特点。把性能瓶颈优化到关键的部分,如对数组的操作用NumPy这样的模块就非常的高效。

theading模块

是最常用的多线程模块,老的thread模块就不用看了

有Thread、Lock、Rock、Condition、Event、Semaphore、BoundedSemphore、Timer、Barrier等一系列可用对象

Thread对象

基本代码

1
2
3
4
5
6
7
# 建立对象
t = threading.Thread(target = function, args = (arg1,arg2))
# 一般来说,Thread线程对象建立之后,不是马上启动的,是用start方法启动
t.start()
# 加入主线程,如果不加入,在主线程退出后仍然运行。join()方法只有在你需要等待线程完成的时候才是有用的
# join如果不被调用 ,将会一直被运行
t.join()

Thread启动后不能用ctrl+c手动终止的解决方法

这里引用别人描述

爬虫作为子线程运行时不受键盘中断信号影响,Ctrl-C无法终止整个爬虫运行。另外的一个场景是多线程压力测试,需要提前终止的情况下,Ctrl-C依旧不能终止整个程序。除了简单粗暴的使用kill命令强行终止之外,本文将给出一个简单可行的解决方案。
可能,python2 和python3对于异常的处理逻辑不一致,2中所有的异常在主线程真正退出时才被捕获。