Python多线程同步机制详解:使用threading.Lock实现互斥
本文深入解析Python多线程中的同步机制,重点介绍threading.Lock类的用法。通过跑道比喻阐明同步互斥概念,演示如何使用acquire和release方法确保数据操作的原子性,避免多线程输出错乱问题。
在多线程程序中,各线程独立运行,导致打印输出的时间顺序往往是混乱的。
观察下图可知,尽管线程创建顺序为t-0、t-1、t-2(按创建时间先后排列),但最终输出结果中t-1反而最晚完成。

那么,我们该如何避免这种输出错乱的情况呢?接下来我们将通过具体方案进行说明。
线程同步
多线程指的是多个独立的执行单元,它们同时执行相同的任务。
既然多线程已经实现了并发执行,为什么还需要同步机制呢?
确实,线程是被同时调用的,但每个线程之间既相互独立,又存在资源竞争。
这就像跑道上有三名运动员,发令枪响后同时起跑,但他们通常不会同时到达终点。
那么,什么是同步?
同步意味着在原本有三名运动员的跑道上,加入同步机制后,任意时刻只允许一名运动员在跑道上。
这听起来似乎有些矛盾:多线程旨在提高多任务处理效率,而同步却限制同一时间只执行一个任务,这是否违背了多线程的初衷?
事实上,同步正是这个意思。我们常将其完整表述为“同步互斥”。总结来说:同步是一种机制,确保跑道上任何时候只有一名运动员;在技术层面,它保证程序数据在任何时刻仅被一个线程操作。
在使用同步机制时,我们需要识别那些需要限制访问的“跑道”,并利用同步机制确保在任意时刻,只有一个“运动员”(线程)在这些资源上运行。
(如果上述解释仍不清楚,建议与同学讨论以上几点)
了解了同步机制后,下面我们来看具体的锁实现。
threading.Lock获取同步锁
threading.Lock是一个类,我们可以利用它来创建锁对象。
什么是锁? 它是维持同步互斥机制的媒介。 相当于跑道设有一扇大门,每次只开门让一名运动员进入跑道。 (注:此处应为运动员,程序员仍需多锻炼。)
如果锁机制失效,后果不堪设想(后续文章将详细探讨)。
下面的代码将用到Lock类的两个关键函数:
acquire函数:用于获取锁。
release函数:用于释放锁。
前文已提及,加上主线程,系统中共有4个线程。
运行以下代码以观察效果:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/21 12:02 上午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : __init__.py.py
# @Project : hello
import threading
import datetime
import time
def dianzan_guanzhu(lock: threading.Lock):
thread_name = threading.current_thread().getName()
print("线程启动了:", thread_name)
now = datetime.datetime.now()
name = "python萌新" + thread_name
lock.acquire()
print("%s - %s name:%s" % (thread_name, now, name))
time.sleep(1)
result = "好棒!" + name + " 关注雷学委,学会了开发知识!"
print("%s - %s result:%s" % (thread_name, now, result))
lock.release()
return result
my_lock = threading.Lock()
for i in range(3):
mythread = threading.Thread(name="t-" + str(i), target=lambda: dianzan_guanzhu(my_lock))
print("mythread:", mythread)
print("is_alive:", mythread.is_alive())
mythread.start()
ac = threading.active_count()
print("active_count:", ac)
以下是运行结果:

我们可以看到,每个线程都完整完成了任务,不再出现三个线程输出相互穿插错乱的情况。
初学者可以通过此例直观感受同步机制的作用与效果。
总结
以上介绍了一种线程协调方案。
线程同步并非指步调一致,而是指同步互斥。
本文到此结束,希望对你有所帮助,也欢迎关注本站更多内容!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













