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

作者:雷学委 时间:2023-06-10 13:57:40 

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

一、举例银行转账

假设现在有一个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万个线程,分别于学委的账户进行转账。

下面是运行结果:

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

运行几次学委的账户还是正确的,余额还是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)

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

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

多线程编程复杂的地方就在这里了, 有时候明明平平无奇的代码,改造成多线程,就很容易出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)

运行结果如下:

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

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

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

三、总结

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

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

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

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

来源:https://levin.blog.csdn.net/article/details/121943332

标签:Python,线程,同步,机制
0
投稿

猜你喜欢

  • Python自动扫雷实现方法

    2023-11-19 19:04:55
  • PHP mysql_result()函数使用方法

    2023-06-13 08:21:29
  • [Oracle] CPU/PSU补丁安装详细教程

    2024-01-27 22:17:52
  • django多文件上传,form提交,多对多外键保存的实例

    2023-04-13 04:24:12
  • python+pillow绘制矩阵盖尔圆简单实例

    2022-07-04 02:44:39
  • JS原生轮播图的简单实现(推荐)

    2024-04-29 14:06:30
  • python库pydantic的简易入门教程

    2022-06-27 14:05:28
  • python 列表递归求和、计数、求最大元素的实例

    2023-01-07 13:28:07
  • Python中二维列表如何获取子区域元素的组成

    2021-02-16 02:41:01
  • golang/python实现归并排序实例代码

    2023-12-13 04:19:01
  • Windows10使用Anaconda安装Tensorflow-gpu的教程详解

    2023-09-21 14:50:15
  • python实现自动下载sftp文件

    2022-01-25 12:55:36
  • python通过tcp发送xml报文的方法

    2021-02-18 08:34:25
  • PDO::prepare讲解

    2023-06-06 06:15:28
  • 举例详解Python中的split()函数的使用方法

    2021-06-23 07:26:49
  • Python+Turtle实现绘制勾股树

    2023-03-04 21:38:36
  • pytorch版本PSEnet训练并部署方式

    2021-01-06 09:41:18
  • 浅析JSON序列化与反序列化

    2024-03-22 12:50:05
  • Python实现随机生成迷宫并自动寻路

    2023-11-18 11:12:41
  • 浅议Wap网页设计中的锚点链接

    2010-12-17 12:41:00
  • asp之家 网络编程 m.aspxhome.com