08. 多线程总结

2020-05-07  本文已影响0人  花间派I风月

1. 线程简介

  1. 线程(Thread)也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。
  2. 线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
  3. 一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

2. 为什么要使用线程

  1. 同一进程中的线程之间共享内存:线程在程序中是独立的、并发的执行流。与分隔的进程相比,进程中线程之间的隔离程度要小,它们共享内存、文件句柄和其他进程应有的状态。
  2. 线程的并发性更高:因为线程的划分尺度小于进程,使得多线程程序的并发性高。进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
  3. 线程比进程的性能更好:这是由于同一个进程中的线程共享同一个进程的虚拟空间。线程共享的环境包括进程代码段、进程的公有数据等,利用这些共享的数据,线程之间很容易实现通信。
  4. 多线程资源消耗更小:操作系统在创建进程时,必须为该进程分配独立的内存空间,并分配大量的相关资源,但创建线程则简单得多。因此,使用多线程来实现并发比使用多进程的性能要高得多。

3. 创建线程的方式

  1. thread模块在python3中更名为_thread.而且将要废弃。
  2. python3中通过threading模块创建多线程,创建方法有两种:

4. 守护线程

  1. 使用setDaemon(True)把所有的子线程都变成了主线程的守护线程,因此当主进程结束后,子线程也会随之结束。所以当主线程结束后,整个程序就退出了。
  2. 把子进程设置为守护线程,必须在start()之前设置。
  3. 为了让守护线程执行结束之后,主线程再结束,我们可以使用join方法,让主线程等待子线程执行
  4. join()在start()之后。

5. 多线程共享全局变量

  1. 线程是进程的执行单元,进程是系统分配资源的最小单位,所以在同一个进程中的多线程是共享资源的。

6. 锁

1. 互斥锁

  1. 线程之间是进行随机调度,多个线程同时修改同一条数据时可能会出现脏数据。
  2. 因此出现了线程锁,即同一时刻允许一个线程执行操作。线程锁用于锁定资源。
  3. 由于线程之间是进行随机调度,如果有多个线程同时操作一个对象,如果没有很好地保护该对象,会造成程序结果的不可预期,我们也称此为“线程不安全”。

2. 递归锁

  1. RLcok类的用法和Lock类一模一样,但它支持嵌套,在多个锁没有释放的时候一般会使用RLcok类。

7. 信号量(BoundedSemaphore类)

  1. 互斥锁同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,
  2. 比如酒店有5个房间,那最多只允许5个人开房,后面的人只能等里面有人出来了才能再进去。

8. 事件(Event类)

  1. python线程的事件用于主线程控制其他线程的执行,事件是一个简单的线程同步对象,其主要提供以下几个方法:
  1. 事件处理的机制:全局定义了一个“Flag”,当flag值为“False”,那么event.wait()就会阻塞,当flag值为“True”,那么event.wait()便不再阻塞。

9. GIL(Global Interpreter Lock)全局解释器锁

  1. GIL的全称是Global Interpreter Lock(全局解释器锁).只是cpython解释器导致与python语言无关,用别的解释器无此问题;
  2. 在python中,无论有多少核,同时只能执行一个线程。究其原因,这就是由于GIL的存在导致的。
  3. cpython解释器为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。
  4. Python多线程的工作过程:
  1. python针对不同类型的代码执行效率也是不同的:
  1. GIL在python中的版本差异:

10. 线程池


concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用

属性:max_workers, 线程池容量

1、submit(fn, *args, **kwargs)
异步提交任务

2、map(func, *iterables, timeout=None, chunksize=1) 
取代for循环submit的操作

3、shutdown(wait=True) 
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前

4、result(timeout=None)
取得结果
5、add_done_callback(fn)
回调函数
6、done()
方法用于判定某个任务是否完成
7、cancel()
cancel方法用于取消某个任务,该任务没有放入线程池中才能取消成功
上一篇 下一篇

猜你喜欢

热点阅读