侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python多线程原理与用法详解

Python  /  管理员 发布于 7年前   165

本文实例讲述了Python多线程原理与用法。分享给大家供大家参考,具体如下:

多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。[1] 在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程(台湾译作“执行绪”),进而提升整体处理性能。

创建并启动一个线程

import threadingdef runtask(name):  print("%s线程已启动"%name)t = threading.Thread(target=runtask,args=("task1",))  # args因为是一个元组,所以必须这样写,否则运行将报错t.start()

join

等待当前线程执行完毕

import threadingimport timedef runtask(name):  print("%s线程已启动"%name)  time.sleep(2)t = threading.Thread(target=runtask,args=("task1",))t.start()t.join()print("abc")  # 过了2s才会打印,若无等待将看不到等待2s的效果

setDaemon(True)

将线程设置为守护线程。若设置为守护线程,主线程结束后,子线程也将结束,并且主线程不会理会子线程是否结束,主线程不会等待子线程结束完后才结束。若没有设置为守护线程,主线程会等待子线程结束后才会结束。

active_count

程序的线程数量,数量=主线程+子线程数量

Lock(互斥锁)

Python编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为” 互斥锁” 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。在Python中我们使用threading模块提供的Lock类。

import threading,timedef runtask(name):  global count  time.sleep(1)  lock.acquire()   # 获取锁资源,并返回是否获取成功  count+=1  print(name,count)  lock.release()   # 释放资源count = 0lock = threading.Lock()   # 互斥锁for index in range(50):  t = threading.Thread(target=runtask,args=("thread%d"%index,))  t.start()

上面这段代码如果没有加上互斥锁,在Python2.x中执行的结果将会是乱的。在Python3.x中执行却总是正确的,似乎是自动为其加了锁

RLock(递归锁,可重入锁)

当一个线程中遇到锁嵌套情况该怎么办,又会遇到什么情况?

def run1():  global count1  lock.acquire()  count1 += 1  lock.release()  return count1def run2():  global count2  lock.acquire()  count2 += 1  lock.release()  return count2def runtask():  lock.acquire()  r1 = run1()  print("="*30)  r2 = run2()  lock.release()  print(r1,r2)count1,count2 = 0,0lock = threading.Lock()for index in range(50):  t = threading.Thread(target=runtask,)  t.start()

这是一个很简单的线程锁死案例,程序将被卡死,停止不动。为了解决这一情况,Python提供了递归锁RLock(可重入锁)。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的代码只需做一些小小的改动

lock = threading.Lock()

修改为:

lock = threading.RLock()

那么程序将不会发生死锁情况。

最大可执行线程

threading.BoundedSemaphore(5)设置可同时执行的最大线程数为5个,后面的线程需排队等待前面的线程执行完毕

import time,threadingdef runtask(name):  global num  semaphore.acquire()  time.sleep(1)  num += 1  semaphore.release()  print(name,num)num = 0semaphore = threading.BoundedSemaphore(5)for index in range(50):  t = threading.Thread(target=runtask,args=("线程%s"%index,))  t.start()

执行效果:

可以看出上面的程序是每次只有5个线程在同时运行,其他线程需等待前面的线程执行完毕,这就是最大可执行线程。

Event

Python提供了Event对象用于线程间通信,它是由线程设置的信号标志,如果信号标志位为假,则线程等待直到信号被其他线程设置成真。Event中提供了四个重要的方法来满足基本的需求。

  • - clear:清除标记
  • - set:设置标记
  • - is_set:是否被标记
  • - wait:等待被标记

代码示例:

import threading,timedef lighter():  num = 0  event.set()   # 设置标记  while True:    if num >= 5 and num < 10:      event.clear()  # 清除标记      print("红灯亮起,车辆禁止通行")    if num >= 10:      event.set()   # 设置标记      print("绿灯亮起,车辆可以通行")      num = 0    num += 1    time.sleep(1)def car():  while True:    if event.is_set():      print("车辆正在跑...")    else:      print("车辆停下了")      event.wait()    time.sleep(1)event = threading.Event()t1 = threading.Thread(target=lighter,)t2 = threading.Thread(target=car,)t1.start()t2.start()

这是一个简单的红灯停绿灯行案例。初始设置为绿灯并标记,车辆看到标记后通行,当红灯亮起的时候取消标记,车辆看到没有标记时停下,等待标记。

Queue队列

使任务按照某一种特定顺序有条不紊的进行。下面介绍几种常用的队列:

  • - queue.Queue():先进先出
  • - queue.LifoQueue():先进后出
  • - queue.PriorityQueue:优先级队列,优先级的值越小,越先执行

下面介绍几种常用的方法:

  • - get():获取item,如果队列已经取空将会卡住。可设置timeout参数,给定一个超时的值,或者设置参数block=False,队列空直接抛异常
  • - get_nowait():b获取item。如果队列取空了,将会直接抛异常
  • - put():放入队列
  • - empty():队列是否为空
  • - qsize():获取队列的item数量

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》、《Python+MySQL数据库程序设计入门教程》及《Python常见数据库操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。


  • 上一条:
    使用python的pandas库读取csv文件保存至mysql数据库
    下一条:
    Python模拟简单电梯调度算法示例
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客