ISEE小语
“人生是一场漫长的修行,我们这一生都在渡,渡人,渡心,渡自己。想要过一个舒服的人生,最重要的是满足自己,而不是讨好别人。”
——《断舍离》
【引言】
本次介绍Python在多线程环境中如何保护共享资源。
使用threading.Lock是Python标准库中的一个同步原语,在某些情况下,多个线程可能会同时访问共享数据,这可能导致数据不一致。使用 threading.Lock进行线程同步,可以保证同一时间只有一个线程可以访问共享资源。
【环境】
Python | 3.9.16 |
接下来我们看一下不使用锁和使用锁的区别
我们来实现一个实例:
实现了一个简单的多线程计数器功能。
首先,定义了一个名为workers的函数。这个函数在被线程执行时,会将counter的值增加100000次。
然后,创建一个空列表threads用于存储线程对象。使用一个循环创建10个线程,每个线程都执行 workers函数。
最后,执行并等所有线程执行完毕。看最终结果。
【不使用锁】
以下实例,为了效果明显,将实例循环了打印10次
# -*- coding: utf-8 -*-
# 不使用锁
import threading
for i in range(10):
counter = 0
def workers():
"""线程工作函数"""
global counter
for _ in range(100000):
counter += 1 # 这里没有使用锁
threads = []
for _ in range(10):
thread = threading.Thread(target=workers)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(f"不使用锁,第{i}次计数器值: {counter}")
(左右滑动查看完整代码)
结果:
分析:
预期逻辑结果:
每个线程都应该将 counter 增加 100000 次,总共有 10 个线程。因此,理论上,最终的 counter 值应该是 10 * 100000 = 1000000。
实际结果的不确定性:
由于没有使用锁,多个线程可能会同时读取和修改 counter 的值。这可能导致数据竞争(race condition),使得某些增量操作被覆盖或丢失。因此,实际输出结果可能不同于理论值,可能会是小于 1000000 的任何值,且在不同的运行中结果可能会有所不同。
【使用锁】
同上,为了效果明显,将实例循环了打印10次
# -*- coding: utf-8 -*-
"""
使用锁
"""
import threading
for i in range(10):
counter = 0
lock = threading.Lock() # 创建一个锁
def workers():
"""线程工作函数"""
global counter
for _ in range(100000):
with lock: # 使用锁保护对 counter 的访问
counter += 1
threads = []
for _ in range(10):
thread = threading.Thread(target=workers)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(f"使用锁,第{i}次计数器值: {counter}")
(左右滑动查看完整代码)
结果:
分析:
当使用锁时,最终输出应该始终是 1000000,因为锁确保了每次只有一个线程可以修改 counter,从而避免了数据竞争。
【总结】
threading.Lock 是多线程编程中一个非常重要的工具,用于确保数据的一致性和安全性。它适用于需要保护共享资源的各种场景,尤其是涉及到写入操作的情况。通过使用 Lock,可以有效防止数据竞争和潜在的错误,确保程序的稳定性和可靠性。
使用场景:
1、共享资源的修改,当多个线程需要同时修改一个共享变量(如计数器、列表等)时,使用 Lock 可以确保每次只有一个线程能够进行修改。
2、保护临界区,当一段代码必须在一段时间内保持一致性(例如,读取及写入数据库、文件等),这段代码被称为临界区。使用 Lock 可以保证任何时刻只有一个线程能执行这段代码。
3、降低死锁发生的可能性,当多个线程需要获取多个锁时,可能会导致死锁。虽然 Lock 本身不能预防死锁,但在适当的设计中使用锁,可以降低死锁发生的可能性。
4、限流和控制访问,在一些情况下,需要控制对某个资源的访问频率。例如,限制同一时间内对文件的访问数量,可以使用锁来管理。
个人观点,在使用中请根据实际项目进行使用。
点个“赞”和“在看”,是对小栈最大的支持!
文章就分享到这儿,喜欢就点个赞吧!