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中pip安装库时出现Read timed out解决办法

    python中pip安装库时出现Read timed out解决办法

    最近需要使用pip库,安装的时候出现问题,本文就详细的介绍一下python中pip安装库时出现Read timed out解决办法,具有一定的参考价值,感兴趣的可以了解一下
    2022-03-03
  • Python详细介绍模型封装部署流程

    Python详细介绍模型封装部署流程

    本文实例讲述了Python模型封装部署的原理与实现方法。封装即是隐藏对象的属性和实现细节,仅对外提供公共访问方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • PHP魔术方法__ISSET、__UNSET使用实例

    PHP魔术方法__ISSET、__UNSET使用实例

    这篇文章主要介绍了PHP魔术方法__ISSET、__UNSET使用实例,本文直接给出代码示例,需要的朋友可以参考下
    2014-11-11
  • 简单掌握Python的Collections模块中counter结构的用法

    简单掌握Python的Collections模块中counter结构的用法

    counter数据结构被用来提供技术功能,形式类似于Python中内置的字典结构,这里通过几个小例子来简单掌握Python的Collections模块中counter结构的用法:
    2016-07-07
  • 超简单的Matplotlib安装与配置教程

    超简单的Matplotlib安装与配置教程

    Matplotlib是Python的第三方绘图库,它非常类似于MATLAB,在使用Matplotlib软件包之前需要对其进行安装,这篇文章主要给大家介绍了关于Matplotlib安装与配置的相关资料,需要的朋友可以参考下
    2023-09-09
  • Pycharm学习教程(6) Pycharm作为Vim编辑器使用

    Pycharm学习教程(6) Pycharm作为Vim编辑器使用

    这篇文章主要为大家详细介绍了最全的Pycharm学习教程第六篇,Pycharm作为Vim编辑器使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Pandas的数据过滤实现

    Pandas的数据过滤实现

    这篇文章主要介绍了Pandas的数据过滤实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • python 实现控制鼠标键盘

    python 实现控制鼠标键盘

    这篇文章主要介绍了python 控制鼠标键盘的示例,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下
    2020-11-11
  • 关于如何使用python的logging库

    关于如何使用python的logging库

    这篇文章主要介绍了关于如何使用python的logging库,logging是Python标准库中用于记录日志的模块。它提供了一种简单但灵活的方法来记录程序中的事件,以便稍后进行调试和分析,需要的朋友可以参考下
    2023-04-04
  • Python文件与文件夹操作大全(非常全面)

    Python文件与文件夹操作大全(非常全面)

    Python具有强大的文件处理功能,如文件的创建、打开、文件内容的写入、读出文件中的内容等等,这篇文章主要介绍了Python文件与文件夹操作,需要的朋友可以参考下
    2023-09-09

最新评论