1、引言/动机
多线程(MT)并行运行相互独立的子任务,提升整个任务的效率。
多线程适合的任务的特点:它们本质上是异步的,需要有多个并发事务,各个事务的运行顺序可以是不确定的,随机的,不可预测的。运算密集型的任务一般较容易分隔成多个子任务。

2、进程和线程
进程有自己的地址空间、内存、数据栈及其他记录运行轨迹的辅助数据。
进程之间使用进程间通讯(IPC)共享信息。OS为进程公平分配时间,进程也可以通过fork和spawn操作完成其他任务。
线程(轻量级进程)所有线程运行在同一个进程中,共享相同的运行环境。线程有自己的指令指针,记录自己运行到什么地方。线程的运行可能被抢占(中断)、暂时挂起(睡眠)。一个进程中各线程间共享一片数据空间,线程之间可以方便共享数据及相互通讯。
竞态条件指多个线程共同访问同一片数据,由于数据访问的顺序不一致有可能导致数据结果的不一致的问题。线程库通过同步原语来控制线程的执行和数据的访问。

3、Python、线程和全局解释器锁
(1)全局解释器锁
Python虚拟机(也叫解释器主循环)控制Python代码执行。在主循环中,同时只有一个线程在执行。对Python虚拟机的访问由全局解释器锁(global interpreter lock,GIL)来控制。
在多线程环境中,Python虚拟机按照以下方式执行。
①设置GIL。
②切换到一个线程去执行。
③运行:a.指定数量的字节码的指令,或者b.线程主动让出控制(可以调用time.sleep(0))
④把线程设置为睡眠状态。
⑤解锁GIL。
⑥再次重复以上所有步骤。
在调用外部代码(如C/C++扩展函数)时,GIL将会被锁定,直到函数结束为止。
(2)退出线程
调用thread.exit()或sys.exit()或抛出一个SystemExit异常等。不过,不可以直接”杀掉“一个线程。

  • thread模块:不建议使用,当线程退出时,所有其它线程没有被清除就退出了。
  • threading模块:可确保所有”重要的“子线程都退出后,进程才会结束。

(3)在Python中使用线程
Python提供了几个用于多线程编程的模块,包括thread、threading和Queue等。
thread和threading用于创建和管理线程。
thread模块提供了基本的线程和锁的支持,而threading模块提供更高级别,功能更强的线程管理功能。threading模块的同步原语更丰富。
不建议使用thread模块:thread功能没有threading完善;thread对线程结束工作没有进行适当的控制。

4、thread模块
thread模块除了产生线程外,也提供了基本的同步数据结构锁对象(lock object,也叫原语锁、简单锁、互斥锁、互斥量、二值信号量)。
(1)模块函数

  • start_new_thread(function,args,kwargs=None)产生一个新线程来运行函数function,该函数前两个参数是必须的,就算运行的函数不需要参数,也要传入一个空元组。
  • allocate_lock() 分配一个LockType类型的锁对象
  • exit() 让线程退出

(2)LockType类型锁对象方法

  • acquire(wait=None)尝试获取锁对象
  • locked() 如果获取了锁对象返回True,否则返回False
  • release() 释放锁

5、threading模块
threading模块提供了Thread类,还提供了各种很好用的同步机制。
(1)threading模块对象

  • Thread 表示一个线程的执行的对象
  • Lock 锁原语对象
  • Rlock 可重入锁对象,使单线程可以再次获得已经获得了的锁(递归锁定)
  • Condition 条件变量对象,能让线程停下来等待其他线程满足了某个”条件”。
  • Event 通用的条件变量。多个线程可以等待某个事件的发生,当事件发生后,所有的线程都会被激活
  • Semaphore 为等待锁的线程提供一个类似“等待室”的结构
  • BoundedSemaphore 与Semaphore类似,只是它不允许超过初始值
  • Timer 与Thread类似,只是它要等待一段时间后才开始执行

(2)Thread类
Thread类可以用多种方法来创建线程。

  • 创建一个Thread类的实例,传给它一个函数。
  • 创建一个Thread类的实例,传给它一个可调用的类对象。
  • 从Thread类派生出一个子类,创建一个这个子类的实例。

Thread类有很多thread模块里没有的函数。

  • start() 开始线程的执行
  • run() 定义线程的功能的函数(一般会被子类重写)
  • join(timeout=None) 程序挂起,直到线程结束;如果给出timeout,则最多阻塞timeout秒
  • getName() 返回线程的名字
  • setName(name) 设置线程的名字
  • isAlive() 表示线程是否还在运行中
  • isDaemon() 返回线程的daemon标志
  • setDaemon(daemonic) 把线程的daemon标志设置为daemonic(一定要在调用start()函数前调用)

(3)threading模块中的其他函数

  • activeCount() 当前活动的线程对象的数量
  • currentThread() 返回当前线程对象
  • enumerate() 返回当前活动线程的列表
  • settrace(func) 为所有线程设置一个跟踪函数
  • setprofile(func) 为所有线程设置一个profile函数

(4)补充
守护线程:若设置一个线程为守护线程,在进程退出时,不用等待这个线程退出。整个Python会在所有的非守护线程退出后才结束。threading模块支持守护线程,thread模块不支持。

  • 使用setDaemon()函数设定线程的daemon标志来设置守护线程。thread.setDaemon(True)就表示这个线程”不重要“
  • thread.isDaemon()函数来判断其daemon标志的值。新的子线程会继承其父线程的daemon标志。

6、Queue模块
Queue模块可以用来进行线程间的通讯,让各个线程之间共享数据。
(1)Queue模块函数

  • queue(size) 创建一个大小为size的Queue对象

(2)Queue对象函数

  • qsize() 返回队列的大小(由于在返回的时候,队列可能会被其它线程修改,所以这个值是近似值)
  • empty() 返回队列是否为空
  • full() 返回队列是否已满
  • put(item,block=0) 把item放到队列中,如果给了block,函数会一直阻塞到队列中有空间位置
  • get(block=0) 从队列中取一个对象,如果给了block,函数会一直阻塞到队列中有对象为止

7 、相关模块

  • thread 基本的、低级别的线程模块
  • threading 高级别的线程和同步对象
  • Queue 供多线程使用的同步先进先出队列
  • mutex 互斥对象
  • SocketServer 具有线程控制的TCP和UDP管理器

更多相关文章

  1. 面试---Python中的模块和包是什么?
  2. python 虚拟机是单线程;当线程执行I/O密集型操作是,ce
  3. python及其模块下载集合
  4. Python随心记--进程、线程
  5. python的turtle模块画折线图
  6. python多线程文件传输范例(C/S)
  7. centos7 安装 Python PIL模块
  8. Python添加默认模块搜索包路径
  9. python 装饰器和 functools 模块

随机推荐

  1. Android WebRTC
  2. 单独编译android模块
  3. 关于Android中android.content.res.Resou
  4. android(25)(android下实现多线程断点下载)
  5. Android Studio新建项目Rendering Proble
  6. Android电池管理
  7. android 蓝牙driver的启动流程
  8. Android中的compileSdkVersion,minSdkVers
  9. LinearLayout布局中layout_weight的用法
  10. android输出log信息