当前位置: 首页 > news >正文

python多线程程序设计 之二

python多线程程序设计 之二

  • 线程同步机制
    • lock对象
      • acquire
      • release
      • locked
    • RLock对象
    • 条件变量
      • 条件变量应用实列
      • 实列代码

线程同步机制

lock对象

原语锁是一种同步原语,锁定时不属于特定线程。在Python中,它是目前可用的最低级别的同步原语,由_thread扩展模块直接实现。

原始锁处于两种状态之一

  • “锁定”
  • “解锁”

lock对象有两个基本方法:acquire() 和release()。

当状态解锁时,acquire()将状态更改为锁定,并立即返回。当状态被锁定时,acquire()会阻塞,直到另一个线程中对release()的调用将其更改为解锁状态,然后acquire()调用将其重置为锁定状态并返回。

release()方法只能在锁定状态下调用;它将状态更改为解锁,并立即返回。如果尝试释放未锁定的锁,则会引发运行时错误。

当多个线程阻塞在 acquire() 中等待状态转为解锁状态时,当调用 release() 将状态重置为解锁时,只有一个线程继续执行;哪一个等待线程继续进行是未定义的,并且可能因实现而异。

所有方法均以原子方式执行。

acquire

acquire(blocking=True, timeout=-1)
获取锁,阻塞或非阻塞。

当参数blocking为True(默认值)时,acquire将阻塞,直到锁解锁,然后将其设置为锁定,并返回True。

当参数blocking为 False时,不阻塞,返回 False;否则,将锁设置为锁定,并返回 True。

当浮点参数timeout设置为正值时,如果一直无法获取锁,则,最多会阻塞timeout指定的秒数。如果参数timeout是-1,则 指定无限等待。当blocking为False时,禁止指定参数timeout。

如果成功获取锁,则返回值为 True,否则返回值为 False。

release

release()
释放锁。这可以从任何线程调用,而不仅仅是已获取锁的线程。

当锁被锁定时,将其重置为解锁,然后返回。如果任何其他线程在等待锁解锁时,被阻塞,则只允许其中一个线程继续进行。

当在未锁定的锁上调用时,会引发 RuntimeError。

locked

locked()

如果已经获取了锁,则返回True。

RLock对象

可重入锁是一种同步原语,同一线程可以多次获取它。在内部,除了原始锁使用的锁定/解锁状态之外,它还使用“所属线程”和“递归级别”的概念。在锁定状态下,某个线程拥有锁;在解锁状态下,没有线程拥有它。

线程调用锁的 acquire() 方法加锁,并调用其 release() 方法解锁。

可重入锁支持上下文管理协议,因此建议使用with而不是手动调用acquire()和release()来处理代码块的锁获取和释放。

RLock 的 acquire()/release() 调用对可以嵌套,这与 Lock 的 acquire()/release() 不同。只有最后的release()(最外层对的release())将锁重置为解锁状态,并允许在acquire()中阻塞的另一个线程继续进行。

acquire()/release() 必须成对使用:每次获取都必须在已获取锁的线程中释放一次。未能多次调用释放来获取锁,可能会导致死锁。

条件变量

条件变量总是与某种类型的锁相关联;锁可以作为参数传入,也可以默认创建一个。当多个条件变量必须共享同一锁时,传入一个很有用。锁是条件对象的一部分,所以不必单独跟踪它。

条件变量遵循上下文管理协议:使用 with 语句在封闭块的持续时间内获取关联的锁。 acquire() 和release() 方法也会调用关联锁的相应方法。

该类的其他方法必须与相关联的锁一起调用。

  • wait()方法释放锁,然后阻塞,直到另一个线程通过调用notify()或notify_all()唤醒它。一旦被唤醒,wait()重新获取锁并返回。还可以指定超时。
  • notify() 方法会唤醒等待条件变量的线程之一。 notify_all() 方法唤醒所有等待条件变量的线程。

notify()和notify_all()方法不会释放锁;这意味着被唤醒的一个或多个线程不会立即从其 wait() 调用中返回,而是仅在调用 notify() 或 notify_all() 的线程最终释放锁所有权时,唤醒的线程才能返回。

使用条件变量的典型编程风格使用锁来同步对某些共享状态的访问;对特定状态更改感兴趣的线程会重复调用 wait() ,直到看到所需的状态,而修改状态的线程在以可能的方式更改状态时,调用 notification() 或 notify_all(),而这个状态正是某个等待的线程期望的状态。

threading.Condition(lock=None)
此类实现条件变量对象。条件变量允许一个或多个线程等待,直到收到另一线程的通知。

如果给出了锁参数而不是 None,则它必须是 Lock 或 RLock 对象,并且它被用作底层锁。否则,将创建一个新的 RLock 对象并将其用作基础锁。

条件变量应用实列

这个实列演示,生产者/消费者程序模型如何使用条件变量同步多线程程序运行。

通过下列的命令行
python multi_thread_app.py 0.5 0.1
你将看到下列的显示
get wait in_ndx: 0 out_ndx: 0
说明消费者处于饥饿状态,通过等待,实现与生产者同步。

通过下列的命令行
python multi_thread_app.py 0.1 0.5
你将看到大量下列的显示
put wait in_ndx: 1 out_ndx: 0
说明生产者处于等待状态,通过等待,实现与消费者同步。

实列代码

下列代码使用条件变量,实现一个循环数组队列。

  • 当队列空时,取数据线程等待
  • 当队列满时,存数据线程等待
from threading import *
from queue import *lock = Lock()
cv = Condition(lock)Q_SIZE = 6
q = [x for x in range(Q_SIZE)]
in_ndx = 0
out_ndx = 0lock_full = Lock()
cv_full = Condition(lock_full)def q_avail():global in_ndx, out_ndxif out_ndx == in_ndx:return Falsereturn Truedef q_full():global in_ndx, out_ndxif (out_ndx + 1) % Q_SIZE == in_ndx:return Truereturn Falsedef q_get():global in_ndx, out_ndxwith cv:while not q_avail():print("get wait in_ndx: {0} out_ndx: {1}".format(in_ndx, out_ndx))cv.wait()v = q[in_ndx]in_ndx = (in_ndx + 1) % Q_SIZEwith cv_full:cv_full.notify()return vdef q_put(v):global in_ndx, out_ndxwith cv_full:while q_full():print("put wait in_ndx: {0} out_ndx: {1}".format(in_ndx, out_ndx))cv_full.wait()with cv:out_ndx = (out_ndx + 1) % Q_SIZEq[out_ndx] = vcv.notify()

下面代码展示生产者/消费者程序模型,它调用上述的循环队列。

import signal
import sys
import time
import randomfrom threading import *
from cond_vars import *def signal_handler(sig, frame):print('You pressed Ctrl+C!')sys.exit(0)signal.signal(signal.SIGINT, signal_handler)class Consumer(Thread):def __init__(self, delay_s):super(Consumer,self).__init__()self.delay_s = delay_sprint("Consumer")def run(self):while True:v = q_get()time.sleep(self.delay_s)class Producer(Thread):def __init__(self, delay_s):super(Producer, self).__init__()self.delay_s = delay_s;print("Producer")    def run(self):while True:       v_list = random.sample(range(1, 5000), 10)for v in range(len(v_list)):time.sleep(self.delay_s)q_put(v_list[v])if __name__ == "__main__":print("Here")count = len(sys.argv)if ( count == 1):consumer_delay = 0.1producer_delay = 0.1elif (count == 2):producer_delay = float(sys.argv[1])consumer_delay = 0.1elif (count >= 3):producer_delay = float(sys.argv[1])consumer_delay = float(sys.argv[2])print("consumer delay: {0} seconds".format(consumer_delay))print("producer delay: {0} seconds".format(producer_delay))t1 = Producer(producer_delay);t2 = Consumer(consumer_delay)t1.start()t2.start()t1.join()t2.join()

相关文章:

python多线程程序设计 之二

python多线程程序设计 之二 线程同步机制lock对象acquirereleaselocked RLock对象条件变量条件变量应用实列实列代码 线程同步机制 lock对象 原语锁是一种同步原语,锁定时不属于特定线程。在Python中,它是目前可用的最低级别的同步原语,由_…...

k8s用StatefulSet部署redis

redis-config.yaml (配置文件) apiVersion: v1 kind: ConfigMap metadata:name: redis-config data:redis.conf: |# Redis general configuration​ bind 0.0.0.0 ​ protected-mode no ​ port 6379 ​ dir /data ​ appendonly yesse…...

flink on k8s

1.修改host文件 vi /etc/hosts 添加如下内容 这样搭集群的时候就不用记ip了 #::1 localhost localhost.localdomain localhost6 localhost6.localdomain6127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 165.154.221.97 tlb-001 k8s01 k8s-m…...

Java集合(八股)

这里写目录标题 Collection 接口List 接口ArrayList 简述 1. ArrayList 和 LinkedList 区别?⭐️⭐️⭐️⭐️2. ArrayList 和 Array 的区别?⭐️⭐️⭐️ArrayList 和 Vector 区别?⭐️⭐️ArrayList 的扩容机制?⭐️⭐️⭐️ Qu…...

python+adb

#!/usr/bin/python env # -*- coding: utf-8 -*- import os import sys import subprocess from time import sleepimport logging logging.basicConfig(levellogging.DEBUG) class ScreenCapture():def get_screen_size(self):"""获取手机分辨率""&q…...

AIGC文本生成

文本生成是一种人工智能技术,它基于深度学习算法,根据给定的提示信息创作出有逻辑、连贯的文本内容。 文本生成所需的输入(提示或Prompt)可以是简单的关键词、一句话概述或是更复杂的指令和上下文信息。文本生成模型通过分析大量…...

系统架构设计师教程 第5章 5.4 软件测试 笔记

5.4 软件测试 5.4.1 测试方法 ★★★★★ 软件测试方法的分类有很多种, 以测试过程中程序执行状态为依据可分为静态测试 (Static Testing,ST) 和动态测试 (Dynamic Testing,DT); 以具体实现算法细节和系统内部结构的相关情况为根据可分黑盒测试、白盒测试和灰盒测…...

ASPICE评估全流程解析:汽车软件开发组织能力的系统化评估

ASPICE(Automotive SPICE)评估的过程是一个系统化和详尽的流程,旨在评估汽车软件开发组织在软件开发过程方面的能力。 以下是ASPICE评估过程的详细描述: 1. 评估准备阶段 a. 确定评估目标和范围 明确评估的目标,如评…...

合并RAR分卷压缩包

因为文件压缩之后体积仍然过大,大家可能会选择进行分卷压缩,那么rar分卷压缩包之后如何合并成一个压缩包文件呢?今天我们来学习rar分卷压缩包,合并成一个的方法。 最基础的方法就是将分卷压缩包解压出来之后,再将文件…...

重生奇迹MU 想去哪就去哪玩 轻松玩转翅膀属性

在重生奇迹MU这个游戏中,玩家需要扫荡各种怪物,勇斗BOSS,与其他玩家激战。在这个充满冒险的旅程中,翅膀是最重要的装备之一。拥有一个属性强大的翅膀,代表着玩家的成长与强大。穿上它,加速你的冒险之旅吧&a…...

Lnux-gcc/g++使用

目录 1.gcc/g介绍 1.什么是 gcc / g 2.gcc/g指令格式 2. gcc / g 实现程序翻译的过程 1.预处理(进行宏替换) 2.编译(生成汇编) 3.汇编(生成机器可识别代码) 4.连接(生成可执行文件或库文件) 1.gcc/g介绍 1.什么…...

用Python创建一个键盘输入捕获程序

目录 简介 环境准备 安装依赖 项目结构 编写代码 1. 导入库 2. 定义回调函数 3. 启动键盘监听器 4. 整合代码 运行程序 结论 简介 在这篇博文中,我们将探索如何使用Python编写一个简单的键盘输入捕获程序。这个程序将实时捕获用户的键盘输入并在控制台中显示出来。…...

Mybatis中Like模糊查询三种处理方式

目录 Mybatis中Like模糊查询三种处理方式 1.通过单引号拼接${} 1)mapper接口 2)Mapper.xml 3)测试代码 4) 测试结果 2.通过concat()函数拼接(个人推荐使用这种) 1)mapper接口 2)Mapper.xml 3)测试代码 4) 测…...

STL值list

list容器 头文件&#xff1a;#include<list> - list是一个双向链表容器&#xff0c;可高效地进行插入删除元素 - list不可以随机存取元素&#xff0c;所以不支持at.(pos)函数与[]操作符 注&#xff1a;list使用迭代器访问数据时可以一步一步走自增自减&#xff08;即…...

结构体的内存对齐

对⻬规则&#xff1a; 1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 2.其他成员变量要对⻬到某个数字&#xff08;对⻬数&#xff09;的整数倍的地址处。 对⻬数编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。 但一些编译器下并没有默认对其数 3.结…...

Web 创建设计

Web 创建设计 Web 创建设计是一个涉及多个方面的过程,它包括网站的视觉设计、用户界面设计、用户体验设计、前端开发以及后端开发等。本文将详细介绍这些方面,并探讨如何创建一个既美观又实用的网站。 1. 视觉设计 视觉设计是网站创建设计的第一步,它决定了网站的外观和感…...

2024年9月16日历史上的今天大事件早读

1151年9月16日 南宋名将韩世忠逝世 1782年9月16日 清朝道光帝旻宁出生 1810年9月16日 墨西哥独立日 1856年9月16日 云南杜文秀领导回民起义 1880年9月16日 左宗棠创办的兰州机器织呢局开工 1908年9月16日 美国通用汽车公司成立 1919年9月16日 周恩来组织参加的觉悟社成立…...

记录工作中遇到的问题(持续更新~)

跨域问题&#xff08;待排查&#xff09; 2024-09-15 【前提】&#xff1a;前端配置了nignx转发&#xff0c;后端设置了跨域拦截&#xff0c;对http://xxxx做了允许跨域。但是访问http://xxx被拦截了&#xff0c;返回403 Forbidden。同样的配置放在另外一套部署的环境上就完全…...

六西格玛咨询:石油机械制造企业的成本控制与优化专家

一、石油机械制造行业现状及主要困扰 随着全球能源需求的日益增长&#xff0c;石油开采和生产设备需求不断增加&#xff0c;石油机械制造行业在过去数十年里得到了迅猛发展。然而&#xff0c;石油机械制造作为一个高度复杂且技术密集的行业&#xff0c;也面临着多重挑战。首先…...

Redis基础数据结构之 quicklist 和 listpack 源码解读

目录标题 quicklist为什么要设计 quicklist&#xff1f;quicklist特点ziplist quicklist数据结构 listpacklistpack是什么&#xff1f;listpack数据结构ziplist干啥去了&#xff1f;为什么有listpack?什么是ziplist的连锁更新&#xff1f;listpack 如何避免连锁更新&#xff1…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...