Python多线程中Lock锁的使用与注意事项

不晚
不晚
发布时间:2026-10-12| 1人浏览过
原创

本文详细解析Python中threading模块的Lock锁机制,通过对比加锁与未加锁的多线程执行结果,说明锁在防止共享资源竞争中的作用。同时指出threading.Lock()对multiprocessing多进程无效,并提供了相关代码示例及实现细节。

在多线程环境下使用Lock锁,可以有效避免多个线程在访问共享资源时产生混乱。例如,当创建多个线程并向一个空列表l中依次添加数字并打印当前列表状态时,若不加锁保护,可能会出现执行顺序交错的情况。

# encoding=utf8
import threading
import time
lock = threading.Lock()
l = []
 
def test1(n):
	lock.acquire()
	l.append(n)
	print l
	lock.release()
 
def test(n):
	l.append(n)
	print l
 
def main():
	for i in xrange(0, 10):
		th = threading.Thread(target=test, args=(i, ))
		th.start()
if __name__ == '__main__':
	main()

运行结果示例如下:

[0] [0, 1] [0, 1, 2] [0, 1, 2, 3][ 0, 1, 2, 3, 4] [0, 1, 2, 3, 4, 5] [0, 1, 2, 3, 4[, 05, , 16, , 27, ]3 , 4, 5, 6[, 07, , 18, ]2 , 3, 4, [50, , 61, , 72, , 83, , 94], 5, 6, 7, 8, 9]

造成上述“混乱”输出的原因是,每个线程同时执行test函数,向列表l追加数字并打印。由于没有同步机制,多个线程可能同时读取、修改或打印列表,导致输出顺序不可预测且格式错乱。

接下来,让每个线程调用经过加锁处理的“test1”函数,观察其运行结果:

[0] [0, 1] [0, 1, 2] [0, 1, 2, 3] [0, 1, 2, 3, 4] [0, 1, 2, 3, 4, 5] [0, 1, 2, 3, 4, 5, 6] [0, 1, 2, 3, 4, 5, 6, 7] [0, 1, 2, 3, 4, 5, 6, 7, 8] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

此时的输出结果变得有序且清晰。这是因为在test1函数中,每次向列表l添加数字并打印之前,都会先调用锁机制。这确保了同一时刻只有一个线程能够执行添加和打印操作,从而避免了并发写入导致的冲突。

通过对比上述两种情况的结果可知,在多线程程序中,当需要“独占”访问共享资源时,必须使用锁来控制并发行为,以防止多个线程同时占用资源引发异常或数据错误。

使用锁时,首先调用acquire()方法,这相当于向其他线程声明“我正在占用该资源,请等待”;当资源使用完毕后,需调用release()方法,通知其他线程“我已释放资源,你们可以使用了”。

Python threading Lock

本文主要通过代码示例说明以下两点:

  • threading.Lock()不影响 multiprocessing
  • .threading.Lock()影响 threading.

具体代码如下:

import threading
import time
from multiprocessing import Pool
_lock = threading.Lock()
def small_func(value):
    """
    添加线程锁
    :param value:
    :return:
    """
    print(value)
    with _lock:
        time.sleep(5)
    return value
def no_small_func(value):
    """
    没有线程锁
    :param value:
    :return:
    """
    print(value)
    # with _lock:
    time.sleep(5)
    return value
def main():
    """
    multiprocessing 是基于进程的,因此线程锁对其不影响,
    :return:
    """
    st = time.time()
    p = Pool(processes=4)
    value = p.map(func=small_func, iterable=range(4))
    et = time.time()
    print(f"all use time: {et - st}")
    print(value)
def main2():
    """
    threading 受到 线程锁 影响
    :return:
    """
    st = time.time()
    thread_list = []
    for temp_value in range(4):
        t = threading.Thread(target=small_func, args=(temp_value,))
        t.start()
        thread_list.append(t)

    for i in thread_list:
        i.join()

    et = time.time()
    print(f"all use time: {et - st}")
    # print(value)
def main3():
    st = time.time()
    thread_list = []
    res = []
    for temp_value in range(4):
        # 不加线程锁就行了
        t = threading.Thread(target=no_small_func, args=(temp_value,))
        t.start()
        thread_list.append(t)

    for i in thread_list:
        v = i.join()
        res.append(v)

    et = time.time()
    print(f"all use time: {et - st}")
    print(res)
if __name__ == '__main__':
    # main()
    # main2()
    main3()

到此这篇关于Python threading中lock的使用的文章就介绍到这了,更多相关Python threading lock使用内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。