进阶——python——多线程(锁对象)

简介: 进阶——python——多线程(锁对象)

同一变量在多线之间是共享的,任何一个变量都可以被所有线程修改,当多个线程一起修改同一变量时,很可能互相冲突得不到正确的结果,造成线程安全问题。通过示例看一下:

import threading
a = 5
def oper(b):
    global a
    a = a - b
    a = a + b
def target(b):
    for i in range(100000):
        oper(b)
if __name__ == '__main__':
    m = 10
    while m > 0:
        t1 = threading.Thread(target=target, args=(1,))
        t2 = threading.Thread(target=target, args=(2,))
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(a)
        m = m - 1

执行结果:

5
5
5
6
6

正常情况下,oper(b) 操作会使 a 的值保持不变,但从多线程的执行结果来看,我们发现出现了错误的结果,并且每次执行的结果可能不同,通常这种问题我们可以使用加锁的方式解决。

threading.Lock

实现原始锁对象的类,一旦一个线程获得一个锁,会阻塞随后尝试获得锁的线程,直到它被释放,通常称其为互斥锁,它是由 _thread 模块直接扩展实现的。它具有如下方法:

acquire(blocking=True, timeout=-1):可以阻塞或非阻塞地获得锁,参数 blocking 用来设置是否阻塞,timeout 用来设置阻塞时间,当 blocking 为 False 时 timeout 将被忽略。

release():释放锁。

locked():判断是否获得了锁,如果获得了锁则返回 True。

threading.RLock

可重入锁(也称递归锁)类,一旦线程获得了重入锁,同一个线程再次获取它将不阻塞,重入锁必须由获取它的线程释放。它具有如下方法:

  • acquire(blocking=True, timeout=-1):解释同上。
  • release():解释同上。

我们对上述代码进行加锁操作,如下所示:

import threading
# 创建锁
lock = threading.Lock()
a = 5
def oper(b):
    # 获取锁
    lock.acquire()
    global a
    a = a - b
    a = a + b
    # 释放锁
    lock.release()
def target(b):
    for i in range(100000):
        oper(b)
if __name__ == '__main__':
    m = 5
    while m > 0:
        t1 = threading.Thread(target=target, args=(1,))
        t2 = threading.Thread(target=target, args=(2,))
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(a)
        m = m - 1

执行结果:

5
5
5
5
5

我们可以尝试多次执行,现在每次都可以获得正确的结果了。

相关文章
|
8月前
|
人工智能 安全 调度
Python并发编程之线程同步详解
并发编程在Python中至关重要,线程同步确保多线程程序正确运行。本文详解线程同步机制,包括互斥锁、信号量、事件、条件变量和队列,探讨全局解释器锁(GIL)的影响及解决线程同步问题的最佳实践,如避免全局变量、使用线程安全数据结构、精细化锁的使用等。通过示例代码帮助开发者理解并提升多线程程序的性能与可靠性。
270 0
|
5月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
396 1
|
5月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
511 0
|
6月前
|
安全 大数据 程序员
Python operator模块的methodcaller:一行代码搞定对象方法调用的黑科技
`operator.methodcaller`是Python中处理对象方法调用的高效工具,替代冗长Lambda,提升代码可读性与性能。适用于数据过滤、排序、转换等场景,支持参数传递与链式调用,是函数式编程的隐藏利器。
212 4
|
7月前
|
数据采集 消息中间件 并行计算
Python多线程与多进程性能对比:从原理到实战的深度解析
在Python编程中,多线程与多进程是提升并发性能的关键手段。本文通过实验数据、代码示例和通俗比喻,深入解析两者在不同任务类型下的性能表现,帮助开发者科学选择并发策略,优化程序效率。
583 1
|
7月前
|
安全 JavaScript Java
Python中None与NoneType的真相:从单例对象到类型系统的深度解析
本文通过10个真实场景,深入解析Python中表示“空值”的None与NoneType。从单例模式、函数返回值,到类型注解、性能优化,全面揭示None在语言设计与实际编程中的核心作用,帮助开发者正确高效地处理“无值”状态,写出更健壮、清晰的Python代码。
708 3
|
7月前
|
Python
解决Python中AttributeError:'image'对象缺少属性'read_file'的问题策略。
通过上述策略综合考虑,您将能够定位问题并确定如何解决它。记住,Python社区很庞大,也很乐于帮助解决问题,因此不要害怕在求助时提供尽可能多的上下文和您已经尝试过的解决方案。
197 0
|
8月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
8月前
|
数据采集 存储 Java
多线程Python爬虫:加速大规模学术文献采集
多线程Python爬虫:加速大规模学术文献采集
|
数据采集 Java 数据处理
Python实用技巧:轻松驾驭多线程与多进程,加速任务执行
在Python编程中,多线程和多进程是提升程序效率的关键工具。多线程适用于I/O密集型任务,如文件读写、网络请求;多进程则适合CPU密集型任务,如科学计算、图像处理。本文详细介绍这两种并发编程方式的基本用法及应用场景,并通过实例代码展示如何使用threading、multiprocessing模块及线程池、进程池来优化程序性能。结合实际案例,帮助读者掌握并发编程技巧,提高程序执行速度和资源利用率。
665 0

热门文章

最新文章

推荐镜像

更多