参考书籍:python核心编程

_thread模块除了可以派生线程外,还提供了基本的同步数据结构,又称为锁对象(lock object,也叫原语锁、简单锁、互斥锁、互斥和二进制信号量)。

下面是常用的线程函数:

函数 描述
start_new_thread(function,args,kwargs=None) 派生一个新的线程,使用给定的args和可选的kwargs来执行function
allocate_lock() 分配LockType对象
exit() 退出线程指令
LockType锁对象的方法
acquire(wait=None) 尝试获取锁对象
locked() 如果获取了锁对象则返回True,否则返回False
release() 释放锁

_thread模块的核心函数是start_new_thread()。专门用来派生新的线程。

我们对上节文章的onethr.py文件稍作修改:

#!/usr/bin/env python

import _thread
from time import sleep,ctime def loop0():
print('开始循环0次在:',ctime())
sleep(4)
print('结束循环0次在:',ctime()) def loop1():
print('开始循环1次在:',ctime())
sleep(2)
print('结束循环1次在:',ctime()) '''
def main():
print('开始于:',ctime())
loop0()
loop1()
print('所有的任务都完成于:',ctime())
''' def main():
print('starting at:', ctime())
_thread.start_new_thread(loop0, ())
_thread.start_new_thread(loop1, ())
sleep(6)
print('all done at:', ctime()) if __name__ =='__main__':
main(

执行该脚本三遍,结果:

PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 21:56:10 2018
开始循环1次在: Mon Mar 26 21:56:10 2018
开始循环0次在: Mon Mar 26 21:56:10 2018
结束循环1次在: Mon Mar 26 21:56:12 2018
结束循环0次在: Mon Mar 26 21:56:14 2018
all done at: Mon Mar 26 21:56:16 2018
PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 22:00:43 2018
开始循环0次在: Mon Mar 26 22:00:43 2018
开始循环1次在: Mon Mar 26 22:00:43 2018
结束循环1次在: Mon Mar 26 22:00:45 2018
结束循环0次在: Mon Mar 26 22:00:47 2018
all done at: Mon Mar 26 22:00:49 2018
PS C:\Users\WC> python E:\Python3.6.3\workspace\mtsleepA.py
starting at: Mon Mar 26 22:00:56 2018
开始循环0次在: Mon Mar 26 22:00:56 2018
开始循环1次在: Mon Mar 26 22:00:56 2018
结束循环1次在: Mon Mar 26 22:00:58 2018
结束循环0次在: Mon Mar 26 22:01:00 2018
all done at: Mon Mar 26 22:01:02 2018

由上面的代码可知,start_new_thread()必须包含两个参数,即使要执行的函数不需要参数,也要传递一个空元组。

我们注意到:loop0还是loop1开始的顺序竟然可以是无序的;loop0和loop1是同时执行的;loop1是在loop0之前结束的;整个程序一共耗时6秒。

我们可以说,loop0和loop1是并发执行的。

我们在主程序(其实也就是主线程)中增加了一个sleep(6)的语句,这其实是为了避免主程序结束的时候,loop0和loop1两个线程还没有结束的问题。这也是_thread模块的一种线程同步机制。

但是,我们要说这样使用sleep()来进行线程同步是不靠谱的,这也是_thread的一个弊端所在。

这时,我们可以引用锁机制来实现相应的线程管理,并且同时改善单独的循环函数实现方式:

import _thread
from time import sleep, ctime
#不再把4秒和2秒硬性的编码到不同的函数中,而是使用唯一的loop()函数,并把这些常量放进列表loops中
loops=[4,2]
#代替了之前的loop*()函数,三个参数分别代表了处于第几个循环中,睡眠时间和锁对象。每个循环执行到最后一句的时候,释放锁对象,告诉主线程该线程已完成
def loop(nloop,sec,lock):
print('开始循环',nloop,'在:',ctime())
sleep(sec)
print('循环',nloop ,'结束于:',ctime())
lock.release() def main():
print('开始于:',ctime())
locks=[]
nloops=range(len(loops)) #第一个for循环中,创建了一个锁的列表,通过thread.allocate_lock()方法得到锁对象,再通过acquire()方法取到锁(相当于把锁锁上),取到之后就可以把它添加到锁列表locks中。
for i in nloops:
lock=_thread.allocate_lock()
lock.acquire()
locks.append(lock)
#第二个for循环中,主要用于派生线程。每个线程都会调用loop()函数,并传递循环号、睡眠时间以及用于该线程的锁。
for i in nloops:
_thread.start_new_thread(loop,(i,loops[i],locks[i]))
#第三个for循环,按照顺序检查每个锁。每个线程执行完毕后,都会释放自己的锁对象。这里使用忙等待,让主线程等所有的锁都释放后才继续执行
for i in nloops:
while locks[i].locked():
pass
print('所有的任务完成于:',ctime()) if __name__ =='__main__':
main()

执行结果:

开始循环 1 在: Mon Mar 26 22:49:25 2018
开始循环 0 在: Mon Mar 26 22:49:25 2018
循环 1 结束于: Mon Mar 26 22:49:27 2018
循环 0 结束于: Mon Mar 26 22:49:29 2018
所有的任务完成于: Mon Mar 26 22:49:29 2018

上述结果除了表名两次循环是并发执行的之外,整个程序一共用时4秒,而不是之前的6秒。

python 多线程编程之_thread模块的更多相关文章

  1. python 多线程编程之threading模块(Thread类)创建线程的三种方法

    摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...

  2. python并发编程之asyncio协程(三)

    协程实现了在单线程下的并发,每个协程共享线程的几乎所有的资源,除了协程自己私有的上下文栈:协程的切换属于程序级别的切换,对于操作系统来说是无感知的,因此切换速度更快.开销更小.效率更高,在有多IO操作 ...

  3. python并发编程之threading线程(一)

    进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源. 系列文章 py ...

  4. Python 多进程编程之multiprocessing--Process

    Python 多进程编程之multiprocessing 1,Process 跨平台的进程创建模块(multiprocessing), 支持跨平台:windowx/linux 创建和启动      创 ...

  5. python并发编程之Queue线程、进程、协程通信(五)

    单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ...

  6. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  7. python并发编程之multiprocessing进程(二)

    python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. 系列文章 python并发编程之threading线程(一) python并 ...

  8. Python网络编程之TCP套接字简单用法示例

    Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...

  9. iOS多线程编程之NSThread的使用

      目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...

随机推荐

  1. java8 Optional优雅非空判断

    java8 Optional优雅非空判断 import java.util.ArrayList;import java.util.List;import java.util.Optional; pub ...

  2. 【Luogu P1981】表达式求值

    点我进入原题Luogu P1981 [解题思路] 仔细分析题目,这就是一道模拟题…… 直接按照符号读入全部的数字,先算乘法,最后把全部数加起来就是结果了 记得要%10000取最后四位 [参考程序] # ...

  3. 科学使用Log4View2

    目录 目录 前言 科学使用 编辑和调试程序集 调试程序集 编辑程序集 结语 推荐文献 目录 NLog日志框架使用探究-1 NLog日志框架使用探究-2 科学使用Log4View2 前言 这个标题很低调 ...

  4. 程序员的算法课(14)-Hash算法-对海量url判重

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  5. CentOS 7 安装 dnsmasq 服务 实现内网DNS

    目录 安装 配置 服务管理 测试解析 安装 废话不多述,上来就安装 yum install -y bind-utils dnsmasq 配置 [root@jenkins ~]# rpm -ql dns ...

  6. 【BZOJ2190】【Luogu P2158】 [SDOI2008]仪仗队

    前言: 更不好的阅读 这篇题解真的写了很久,改了又改才成为这样的,我不会写题解但我正在努力去学,求通过,求赞... 题目: BZOJ Luogu 思路: 像我这样的数论菜鸡就不能一秒切这题,怎么办呢? ...

  7. [学习笔记] [数据分析] 02、NumPy入门与应用

    01.NumPy基本功能 ※ 数据类型的转换在实际操作过程中很重要!!! ※ ※ ndarray的基本索引与切片 ※ 布尔型数组的长度必须跟被索引的轴长度一致 花式索引是利用“整数数组”进行索引. 整 ...

  8. MVC WebApi 返回字符串

    [HttpGet] public HttpResponseMessage GetWebConfigValue(string key) { var response = Request.CreateRe ...

  9. 顺序队列与链式队列--C语言实现

    关于队列,因为我自己在平时使用不多,所以在这里直接将队列的两种存储方式放在一起,作为一篇随笔,这两份代码均可直接运行,亲测.注释写的应该也算比较详细了,就不过多的解释了 顺序队列 #include&l ...

  10. Delphi7 - Server Monitor开发并实现指定端口定时刷新、重启和邮件提醒等功能

    项目背景 近期,总经办邮件反馈考勤数据频繁丢失,请IT排查其根本原因,并提供整改措施. 措不及防,这个项目当初并不是IT主导的,是设备部采购,然后协同软件供应商直接安装.部署和调试的,IT只是提供几个 ...