Python线程之同步机制实际应用场景举例说明

 更新时间:2022年02月24日 10:04:32   作者:雷学委  
这篇文章主要给大家分享的是Python线程之同步机制实际应用场景举例说明,银行转账小栗子供大家参考学习,希望对你有一定的帮助

这次让我们来看看一个真实场景吧:银行转账

一、举例银行转账

假设现在有一个xuewei的账号里面有 100W。

然后有多个任务在转账,转入转出都是跟这个xuewei账号相关的。

而且这些任务发生是随机的。

我们先把上面的场景写成代码:

xuewei_account = 100


# amount为负数即是转出金额
def transfer(money):
    global xuewei_account
    xuewei_account += money

下面是多个线程,多线程模拟转账事件,我们假设有4个事件在同时发生。

import random
import threading
import datetime
import time

xuewei_account = 100


# amount为负数即是转出金额
def transfer(money):
    global xuewei_account
    xuewei_account += money


# 创建4个任务给学委账户转账
for i in range(10000):
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()

# 等待活跃线程只剩下主线程MainThread
time.sleep(10)
print("-" * 16)
print("活跃线程数:", threading.active_count())
print("活跃线程:", threading.current_thread().name)
print("学委账户余额:", xuewei_account)

这里启动了4个线程循环了10000次,也就是4万个线程,分别于学委的账户进行转账。

下面是运行结果:

运行几次学委的账户还是正确的,余额还是100W。

上面的代码线程几万个,但每次运行的操作都很简单,完成一次加法。

线程一个接一个start,非常快速就切换下一个线程, 我们看到程序没有出现问题。

下面进行改造,这次不要就4万线程了,我们让转账这个任务耗时更多,每启动一个线程进行模拟10万次转账。

import random
import threading
import datetime
import time

xuewei_account = 100


# amount为负数即是转出金额
def transfer(money):
    global xuewei_account
    for x in range(100000):
        xuewei_account += money

 创建4个任务给重复学委账户转账:

for i in range(10):
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()

time.sleep(10)
print("-" * 16)
print("活跃线程数:", threading.active_count())
print("活跃线程:", threading.current_thread().name)
print("学委账户余额:", xuewei_account)

这里运行的结果就比较出乎意料了:

多线程编程复杂的地方就在这里了, 有时候明明平平无奇的代码,改造成多线程,就很容易出bug!

当然上面的代码并不是平平无奇,相比第一段代码,上面的转账函数做的事件更多,更耗时。

二、问题解决

我们加上锁

代码如下:

import random
import threading
import datetime
import time

xuewei_account = 100

lock = threading.Lock()
# amount为负数即是转出金额
def transfer(money):
    lock.acquire()
    global xuewei_account
    for x in range(100000):
        xuewei_account += money
    lock.release()


# 创建4个任务给重复学委账户转账
for i in range(10):
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()
    threading.Thread(target=lambda: transfer(-1)).start()
    threading.Thread(target=lambda: transfer(1)).start()

time.sleep(10)
print("-" * 16)
print("活跃线程数:", threading.active_count())
print("活跃线程:", threading.current_thread().name)
print("学委账户余额:", xuewei_account)

运行结果如下:

上面的代码不管怎么运行,运行多少次最后学委的账户都是100.(PS:学委不会联系读者转账的,这个特别注意)。

不管多少个线程,每次转账函数内部转账的代码(从global到 += money这一段代码)只会被一个线程调用。

三、总结

展示了同步机制解决一些编程问题的思路。读者可以多多借鉴,思考锁的应用。

为什么在对amount重度操作(本文第二段代码)的时候,计算就出错了!

这里amount相当于多线程都在操作的变量,也就是共享变量,多线程编程要特别注意这类变量,避免出现对共享变量的操作,有些程序在并发规模很小的时候一点问题也没有。

并发编程是高度利用CPU计算能力的编程方式,并发程序也就是在并行执行同类任务的程序。这个可以跟单线程应用比较。

到此这篇关于Python线程之同步机制实际应用场景举例说明的文章就介绍到这了,更多相关Python线程同步机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中无限循环需要什么条件

    Python中无限循环需要什么条件

    在本篇文章里小编给大家分享的是关于Python中无限循环的条件的相关文章,需要的朋友们可以参考下。
    2020-05-05
  • pycharm终端解释器与Python解释器配置

    pycharm终端解释器与Python解释器配置

    这篇文章主要介绍了pycharm终端解释器与Python解释器配置,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-06-06
  • 基于pytorch实现对图片进行数据增强

    基于pytorch实现对图片进行数据增强

    图像数据增强是一种在训练机器学习和深度学习模型时常用的策略,尤其是在计算机视觉领域,具体而言,它通过创建和原始图像稍有不同的新图像来扩大训练集,本文给大家介绍了如何基于pytorch实现对图片进行数据增强,需要的朋友可以参考下
    2024-01-01
  • 解决IDEA 的 plugins 搜不到任何的插件问题

    解决IDEA 的 plugins 搜不到任何的插件问题

    这篇文章主要介绍了解决IDEA 的 plugins 搜不到任何的插件问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • mac下pip、conda、homebrew修改为清华镜像源的方法

    mac下pip、conda、homebrew修改为清华镜像源的方法

    本文主要介绍了mac下pip、conda、homebrew修改为清华镜像源的方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Python爬取读者并制作成PDF

    Python爬取读者并制作成PDF

    本文是在学习了beautifulsoup之后,制作的一个爬取读者杂志并使用reportlab制作成pdf的python小工具,咱也文艺一下:),分享给大家,有需要的小伙伴参考下吧。
    2015-03-03
  • Python面向对象编程(一)

    Python面向对象编程(一)

    本文详细讲解了Python的面向对象编程,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • 基于Keras的扩展性使用

    基于Keras的扩展性使用

    这篇文章主要介绍了Keras的扩展性使用操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • python实现将两个文件夹合并至另一个文件夹(制作数据集)

    python实现将两个文件夹合并至另一个文件夹(制作数据集)

    这篇文章主要介绍了python实现将两个文件夹合并至另一个文件夹(制作数据集),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Python+Turtle绘制可爱的可达鸭

    Python+Turtle绘制可爱的可达鸭

    一年一度的六一儿童节又来了,祝大朋友小朋友节日快乐!本文主要介绍如何运用Python中的turtle库控制函数绘制可达鸭,希望你会喜欢
    2022-05-05

最新评论