线程是一个操作系统级别的概念,编程语言本身不创建线程,而是调用操作系统层提供的接口创建、控制、销毁线程实例。

他们所支持的线程底层实现和操作效果也是不尽相同的。不过一个操作系统支持的线程至少会有四种状态:就绪、执行、阻塞和终结。线程在四种状态下进行切换,都是要消耗不少的CPU计算能力的。

并且根据操作系统使用线程的进程的不一样,线程还分为用户线程和操作系统线程。操作系统线程(内核线程),是指操作系统内核为了完成硬件接口层操作,由操作系统内核创建的线程:例如I/O操作的内核线程,这些线程应用程序是不能干预的;用户线程,是指用户安装/管理的应用程序,为执行某一种操作,而由这个应用程序创建的线程。

线程在创建时,操作系统不会为这个线程分配独立的资源(除了必要的数据支撑)。一个应用程序(进程)下的所有线程,都是共享这个应用程序(进程)中的资源,例如这个应用程序的CPU资源、I/O资源、内存资源。

多线程是一门编程语言的重要操作。

GIL(全局解释器锁)存在于python解释器中,用来确保当前只有一个线程被执行,当一个线程获得GIL后,这个线程将被执行,在python2中,执行了一定数量的字节码,或者遇到IO操作会退出释放GIL,在python3.2以后,使用了新的GIL,新的GIL实现中用一个固定的超时时间来指示当前的线程放弃全局锁。在当前线程保持这个锁,且其他线程请求这个锁时,当前线程就会在5毫秒后被强制释放该锁。由下一个获得GIL的线程执行,这导致了纯Python代码使用多线程并不能提高运行速率,只是在遇到需要等待操作的时候,使用多线程会提升效率。

python多线程有两个模块,threading和thread,一般情况下使用threading,特殊情况才使用thread,下面是原因:

  1. threading模块对同步原语的支持更为完善和丰富。
  2. threading模块在主线程和子线程交互上更为友好。
  3. thread模块不支持守护线程。

    thread模块中主线程退出的时候。所有的子线程不论是否还在工作,都会被强制结束。
  4. python3中已经不存在thread模块。

Python多线程支持两种方式来创建线程:一种是继承Thread类,重写他的run()方法,另一种是创建一个threading.Thread对象,在它的初始化函数中(init())中可将调用对象作为参数传输。

常用Threading模块的方法:

  • threading.Thread(self, group=None, target=None, name=None,

    args=(), kwargs=None, verbose=None))
target: 指定线程由 run () 方法调用的可调用对象。默认为 None, 意味着不调用任何内容。
name: 指定该线程的名称。 在默认情况下,创建一个唯一的名称。
args: target调用的实参,元组格式。默认为 (),即不传参。
daemon: 为False表示父线程在运行结束时需要等待子线程结束才能结束程序,为True则表示父线程在运行结束时,子线程无论是否还有任务未完成都会跟随父进程退出,结束程序。(python2和3可能有区别)
  • start方法和run方法
start() 方法是启动一个子线程,线程名就是我们定义的name
run() 方法并不启动一个新线程,就是在主线程中调用了一个普通函数而已。
想启动多线程,就必须使用start()方法。
  • threading.Timer(interval, function, args=[], kwargs={})

threading的派生类,可以用来定时任务,如果要重复执行某个任务,可以在function中再定义一个threading.time()

  • threading.current_thread().name (或者threading.current_thread().getName())

线程名,只是一个标识符,可以使用getName()、setName()获取和运行时重命名。

  • threading.current_thread().ident

线程ID,非0整数。线程启动后才会有ID,否则为None。线程退出,此ID依旧可以访问。此ID可以重复使用

  • threading.current_thread().is_alive()

返回线程是否存活,布尔值,True或False。

  • threading.active_count()

返回当前活跃的Thread对象数量。返回值和通过enumerate()返回的列表长度是相等的。

  • join([timeout])方法
threading.Thread.join。主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用线程的join方法。
里面的参数时可选的,代表线程运行的最大时间,即如果超过这个时间,不管这个此线程有没有执行完毕都会被回收,然后主线程或函数都会接着执行的。
join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞,设置为None则等待子进程执行完毕
  • setDaemon()方法

主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.这就是setDaemon方法的含义,这基本和join是相反的。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起。

在CPU密集型任务下,多进程更快,或者说效果更好;而IO密集型,多线程能有效提高效率。

python的两个多进程库

subprocess和multiprocess

区别:

subprocess:

subprocess 用来执行其他的可执行程序的,即执行外部命令。 他是os.fork() 和 os.execve() 的封装。 他启动的进程不会把父进程的模块加载一遍。使用subprocess的通信机制比较少,通过管道或者信号机制.

由于在windows中没有os.fork,所以创建进程采用的是createprocess()

Linux的进程创建是通过系统调用fork()

multiprocessing:

multiprocessing 用来执行python的函数,他启动的进程会重新加载父进程的代码。可以通过Queue、Array、Value等对象来通信。

subprocess 用来执行外部命令,是os.fork() 和 os.execve() 的封装,即先fork一个子进程,再运行新的外部程序,子进程不会把父进程的模块加载一遍;

而multiprocessing的原理是fork,fork()调用:调用1次,返回两次--操作系统自动把当前进程(父进程)复制了一份(子进程),然后,分别在父进程和子进程内返回,父进程返回子进程的pid,子进程返回0,即父进程和子进程都在运行。

对于外部调用来说,使用multiprocessing太占资源。

进程之间是数据隔离的,想通讯要用特殊的方式。

在windows中必须把Process()放到if name == "main"语句下

由于Windows没有fork,多处理模块启动一个新的Python进程并导入调用模块。

如果在导入时调用Process(),那么这将启动无限继承的新进程(或直到机器耗尽资源)。

这是隐藏对Process()内部调用的原,使用if name == “__main __”,这个if语句中的语句将不会在导入时被调用。

由于Python运行过程中,multiprocess新创建进程后,进程会导入正在运行的文件,即在运行代码0.1的时候,代码在运行到mp.Process时,新的进程会重新读入改代码,对于没有if name=="main"保护的代码,新进程都认为是要再次运行的代码,这是子进程又一次运行mp.Process,但是在multiprocessing.Process的源码中是对子进程再次产生子进程是做了限制的,是不允许的,于是出现如上的错误提示。

进程之间的通讯可以通过Value和Array进行,Value是单个变量,Array是数组

from multiprocess import Value,Array

num = Value('d', 0.0)

arr = Array('i', range(10))

创建num和arr时,“d”和“i”参数由Array模块使用的typecodes创建:“d”表示一个双精度的浮点数,“i”表示一个有符号的整数,这些共享对象将被线程安全的处理。小写是有符号,大写是无符号。

print(num.value)

print(arr[0])

‘c’: ctypes.c_char     ‘u’: ctypes.c_wchar    ‘b’: ctypes.c_byte     ‘B’: ctypes.c_ubyte

‘h’: ctypes.c_short    ‘H’: ctypes.c_ushort   ‘i’: ctypes.c_int      ‘I’: ctypes.c_uint

‘l’: ctypes.c_long,    ‘L’: ctypes.c_ulong    ‘f’: ctypes.c_float    ‘d’: ctypes.c_double

Python多线程操作的更多相关文章

  1. python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)

    今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系 ...

  2. python 多线程操作数据库

    如果使用多线程操作数据库,容易引起多用户操作锁表 OperationalError: (2013, 'Lost connection to MySQL server during query') 使用 ...

  3. 一行 Python 实现并行化 -- 日常多线程操作的新思路

    春节坐在回家的火车上百无聊赖,偶然看到 Parallelism in one line 这篇在 Hacker News 和 reddit 上都评论过百的文章,顺手译出,enjoy:-) http:// ...

  4. python多线程学习记录

    1.多线程的创建 import threading t = t.theading.Thread(target, args--) t.SetDeamon(True)//设置为守护进程 t.start() ...

  5. python 多线程学习

    多线程(multithreaded,MT),是指从软件或者硬件上实现多个线程并发执行的技术 什么是进程? 计算机程序只不过是磁盘中可执行的二进制(或其他类型)的数据.它们只有在被读取到内存中,被操作系 ...

  6. <转>Python 多线程的单cpu与cpu上的多线程的区别

    你对Python 多线程有所了解的话.那么你对python 多线程在单cpu意义上的多线程与多cpu上的多线程有着本质的区别,如果你对Python 多线程的相关知识想有更多的了解,你就可以浏览我们的文 ...

  7. Python多线程和Python的锁

    Python多线程 Python中实现多线程有两种方式,一种基于_thread模块(在Python2.x版本中为thread模块,没有下划线)的start_new_thread()函数,另一种基于th ...

  8. Python多线程锁

    [Python之旅]第六篇(四):Python多线程锁   python lock 多线程 多线程使用方法 多线程锁 摘要:   在多线程程序执行过程中,为什么需要给一些线程加锁以及如何加锁,下面就来 ...

  9. Day9 - Python 多线程、进程

    Python之路,Day9, 进程.线程.协程篇   本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...

随机推荐

  1. Linux iptables用法与NAT

    1.相关概念 2.iptables相关用法 3.NAT(DNAT与SNAT) 相关概念 防火墙除了软件及硬件的分类,也可对数据封包的取得方式来分类,可分为代理服务器(Proxy)及封包过滤机制(IP ...

  2. MIP开发教程(三) 使用MIP-CLI工具调试组件

    一 . 在 mip-extensions 仓库中创建新的组件 二 . 预览调试组件 三 . 在 MIP 页中引用自己编写的 MIP 组件 四 . 组件提交到 GitHub 仓库时需要进行校验 站长开发 ...

  3. 漫谈Linux标准的文件系统(Ext2/Ext3/Ext4)

    Ext 全称Linux extended file system, extfs,即Linux扩展文件系统,Ext2就代表第二代文件扩展系统,Ext3/Ext4以此类推,它们都是Ext2的升级版,只不过 ...

  4. markdown用法

    Markdown 语法的目标是成为一种适用于网络的书写语言.不在 Markdown 涵盖范围之内的标签,都可以直接在文档里面用 HTML 撰写.不需要额外标注,只要直接加标签就可以了. 一.常用部分 ...

  5. shell脚本获取进程ID并杀死的实现及问题解析

    经常需要杀死某个进程,操作了几次之后,对一个熟练的码农来说,就要制作自己的工具了.有些工具虽然很小,但是却能节省一大部分的时间. 输入某个进程的ID并杀死的方法.这种事情,一般是先搜索再进行优化,这种 ...

  6. Python爬虫入门教程 49-100 Appium安装+操作51JOB_APP(模拟手机操作之一)手机APP爬虫

    爬前准备工作 在开始安装Appium之前,你要先知道Appium是做什么的?Appium 是一个自动化测试开源工具,看到没,做测试用的,它有点类似Selenium,可以自动操作APP实现一系列的操作. ...

  7. DeviceUuidFactory【获取设备唯一标识码的UUID(加密)】【需要运行时权限的处理的配合】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 有时需要对用户设备进行标识,所以希望能够得到一个稳定可靠并且唯一的识别码.虽然Android系统中提供了这样设备识别码,但是由于An ...

  8. 强化学习(五)用时序差分法(TD)求解

    在强化学习(四)用蒙特卡罗法(MC)求解中,我们讲到了使用蒙特卡罗法来求解强化学习问题的方法,虽然蒙特卡罗法很灵活,不需要环境的状态转化概率模型,但是它需要所有的采样序列都是经历完整的状态序列.如果我 ...

  9. 用SpringCloud进行微服务架构演进

    在<架构师必须要知道的阿里的中台战略与微服务> 中已经阐明选择SpringCloud进行微服务架构实现中台战略,因此下面介绍SpringCloud的一些内容,SpringCloud已经出来 ...

  10. 盘点 Python 中的那些冷知识(一)

    小明在日常Code中遇到一些好玩,冷门的事情,通常都会记录下来. 现在已经积攒了一些了,最近打算整理一波,发出来给大家补补.一篇只分享五个,有时间了就整理.不想错过的,千万记得关注一下. 1. 省略号 ...