【Python实战】global关键字的应用和线程并发

请添加图片描述

【Python实战】global关键字的应用和线程并发

  • 一、前言
    • 编译环境
  • 二、gloabl全局变量关键字
    • 代码示例
  • 三、程序运行时全局变量的变化
    • 代码示例
  • 四、全局变量的线程安全问题
  • 五、总结

在很多场景和业务实践中,线程之间的变量共享和保持原子性非常的关键和重要。

这边主要解决在代码实践中,如何在异步多线程中改变同一个变量和保持这个变量的原子性。

一、前言

编译环境

Python版本:3.11.7

IDE:PyCharm 2023.3.2

二、gloabl全局变量关键字

在Python中,global 是一个关键字,用于在函数内部声明一个全局变量。

当你在一个函数内部想要修改全局作用域的变量时,就需要使用 global 关键字。

以下示例展示如何在方法中改变全局变量的值。

代码示例


x = 10  # 全局变量def modify_global_variable():global x  # 使用global关键字声明要修改的是全局变量xx = 20modify_global_variable()print(x)  # 打印全局变量x的值,输出为 20

三、程序运行时全局变量的变化

在项目实战中,必不可少的是如何实时改变这个全局变量的值来配合业务上各种需求的使用。

以下示例让我们来看一下, 全局变量的值在实时改变中,是怎么实现的。

代码示例

import threading
from time import sleep# 初始化一个变量列表用来实时改变全局变量
variable_list = ['Qian', 'Kun', 'Li', 'Kan', 'Dui', 'Zhen', 'Xun', 'Gen']# 初始化变量a
a = ''# 初始化变量b
b = ''# 此方法用来实现在程序运行中,不停的切换变量a和变量b的值
def divination():# 声明全局变量a和bglobal a, bwhile True:# 循环列表中的值赋给变量a和bfor i in range(len(variable_list)):a = variable_list[i]# 这边用三目来判断一下索引,避免索引异常b = variable_list[i + 1] if i < len(variable_list) - 1 else variable_list[0]# 每一秒改变一次变量a和b的值sleep(1)# 用异步线程来实现变量切换,用守护线程来让线程在后台运行
threading.Thread(target=divination, daemon=True).start()# 主线程,用来打印变量a和b的实时变化
while True:# 这边使用同一行覆盖打印print(f'\r变量a: {a},变量b:{b}', end='', flush=True)# 后台线程运行和主线程之间会有几毫秒的间隔# 为了确保打印变量a和b每次改变的值# 这边每次循环都延迟10mssleep(1.01)

四、全局变量的线程安全问题

在很多业务情况中,会经常出现线程之间互相竞争导致阻塞等等问题

这边我们尝试模拟一下在Python中的类似情况

代码如下:

import threading# 初始化计数值
counter = 0def increment_counter():global counter# 读取当前计数值current_value = counter# 模拟一些耗时的计算# 在这里,可能会有其他线程修改了 counter 的值# 在实际应用中,这个操作可能会更加复杂for _ in range(1000000):pass# 增加计数值counter = current_value + 1# 创建两个线程同时修改计数值
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)thread1.start()
thread2.start()thread1.join()
thread2.join()print("最后计数:", counter)

运行结果counter多数为1,偶尔会为2

在这个例子中,increment_counter 函数首先读取当前计数值,然后进行一些模拟的耗时计算,最后将计数值加一写回到 counter。

由于这个操作不是原子的,两个线程可能同时读取相同的 counter 值,并在模拟计算之后分别增加它,导致最终的计数值不是期望的结果。

为了解决这个问题,可以使用锁来确保对 counter 的操作是原子的。

代码如下:

import threading# 初始化计数值
counter = 0# 创建锁
counter_lock = threading.Lock()def increment_counter():global counterwith counter_lock:# 读取当前计数值current_value = counter# 模拟一些耗时的计算for _ in range(1000000):pass# 增加计数值counter = current_value + 1# 创建两个线程同时修改计数值
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)thread1.start()
thread2.start()thread1.join()
thread2.join()print("z最后计数:", counter)

运行结果始终为2

通过使用锁,确保在任何时刻只有一个线程可以执行对 counter 的操作,从而避免了竞争条件。

五、总结

全局变量在使用过程中,得注意非原子操作变量产生竞争条件导致结果不一致的问题

在高并发情况下,一定不要忘记在使用global关键字时,使用threading.Lock()来保证线程安全

在这里插入图片描述
我欲乘风归去,又恐琼楼玉宇。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/327550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS 开发基础(五)Button

HarmonyOS 开发基础&#xff08;五&#xff09;Button Entry Component struct Index {build() {Row() {Column() {// Button&#xff1a;ArkUI 的基础组件 按钮组件// label 参数&#xff1a;文字型按钮Button(我是按钮)// width&#xff1a;属性方法&#xff0c;设置组件的宽…

Python如何生成个性二维码

Python-生成个性二维码 一、问题描述 通过调用MyQR模块来实现生成个人所需二维码。 安装&#xff1a; pip install myqr 二、代码实现 1.普通二维码 from MyQR import myqr # 普通二维码 myqr.run(wordshttp://www.csdn.net/mayi0312,save_nameqrcode.png ) 效果图&#…

Vue2商品规格选择

Vue2Element-ui Vu2仿写拼多多商家后台规则选择&#xff0c;为什么用Vue2呢&#xff0c;因为公司用的Vue2... 样式不是很好看&#xff0c;自己调一下就行。 <template><div ref"inputContainer"><div>{{ combinationsResult }}</div><…

【开源】基于JAVA语言的智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…

【响应式编程-05】Lambda方法引用

一、简要描述 Lambda的方法引用也叫引用方法 方法引用初体验方法引用的底层实现方法引用的语法格式方法引用举例 静态方法引用构造方法引用普通方法引用super和this方法引用数组的方法引用 二、方法引用初体验 为什么出现方法引用&#xff1f; 引用已存在方法&#xff0c;避免重…

DBeaver配置类Navicat显示字段是否非空

在Navicat中设计表时可以很方便的看到字段是否【非空】&#xff0c;而在DBeaver中确实这样显示的,必须双击字段才能看到是否【非空】 解决方案 点击此处齿轮按钮,将【非空】以及其他需要的显示字段都勾上,重新打开即可

Python中的有序字典是什么

有序字典 一、简介 Python中的字典的特性&#xff1a;无序性。 有序字典和通常字典类似&#xff0c;只是它可以记录元素插入其中的顺序&#xff0c;而一般字典是会以任意的顺序迭代的。 二、普通字典 #! /usr/bin/env python3 # -*- coding:utf-8 -*- d1 {} d1[a] A d1[b…

【Java EE初阶七】多线程案例(生产者消费者模型)

1. 阻塞队列 队列是先进先出的一种数据结构&#xff1b; 阻塞队列&#xff0c;是基于队列&#xff0c;做了一些扩展&#xff0c;适用于多线程编程中&#xff1b; 阻塞队列特点如下&#xff1a; 1、是线程安全的 2、具有阻塞的特性 2.1、当队列满了时&#xff0c;就不能往队列里…

druid Communications link failure报错处理

现象 日志报错&#xff1a;com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 原因 从数据库连接池拿到了已经关闭的连接&#xff0c;导致报错。druid有定时任务进行空闲连接的检测和回收&#xff0c;当连接时长超过mysql的连接超时时间…

YOLOv8改进 | 2023主干篇 | FasterNeT跑起来的主干网络( 提高FPS和检测效率)

一、本文介绍 本文给大家带来的改进机制是FasterNet网络,将其用来替换我们的特征提取网络,其旨在提高计算速度而不牺牲准确性,特别是在视觉任务中。它通过一种称为部分卷积(PConv)的新技术来减少冗余计算和内存访问。这种方法使得FasterNet在多种设备上运行速度比其他网络…

【Flink精讲】Flink数据延迟处理

面试题&#xff1a;Flink数据延迟怎么处理&#xff1f; 将迟到数据直接丢弃【默认方案】将迟到数据收集起来另外处理&#xff08;旁路输出&#xff09;重新激活已经关闭的窗口并重新计算以修正结果&#xff08;Lateness&#xff09; Flink数据延迟处理方案 用一个案例说明三…

C# Attribute特性实战(1):Swtich判断优化

文章目录 前言简单Switch问题无参Swtich方法声明Swtich Attribute声明带有Swtich特性方法主方法结果 有参Switch修改代码修改运行过程运行结果 总结 前言 在经过前面两章内容的讲解&#xff0c;我们已经简单了解了如何使用特性和反射。我们这里解决一个简单的案例 C#高级语法 …