首页 > 解决方案 > 为什么使用锁来读/写共享内存比不使用锁要快

问题描述

我正在试验 Python 多处理,我很惊讶在使用锁时看到反直觉的结果。

我的假设是,在使用共享内存时,如果我们使用锁来确保一次只有一个进程可以访问共享对象,那么所有其他进程将等待锁定进程释放锁,然后再读取/写入共享对象. 因此,尽管这确保了数据完整性并消除了竞争条件,但这也不可避免地导致除了一个进程之外的所有进程都在等待锁定进程。结果,执行的总时间将比不使用锁时长。如果不使用锁,所有进程都不会相互等待,因此会更快完成,但也会损坏数据。

考虑到这种理解,我编写了一个快速程序来确定使用锁到底慢了多少,但令人惊讶的是,使用锁似乎实际上要快得多。

你能解释一下为什么使用锁更快吗?我对锁如何工作的理解有问题吗?或者我设置实验的方式有问题(下面的代码)。

如果lock.acquire()lock.release()注释掉,所以不使用锁,它需要75.85秒,
如果lock.acquire()lock.release()取消注释,所以使用锁,需要57.17
我使用 Python 3.7,在 Intel i7 8550U 上运行,4 个物理内核,(8 个超线程线程)

import os
import multiprocessing as mp
from timeit import default_timer as timer


def func(n, val, lock, add):
    for i in range(n):
        lock.acquire()  # uncomment to use lock
        if add:
            val.value += 1
        else:
            val.value -= 1
        lock.release()  # uncomment to use lock
        if i % (n/10) == 0:
            print(f"Process: {os.getpid()}, {(i / n * 100):.2f}%")


if __name__ == "__main__":
    start = timer()
    lock = mp.Lock()
    n = 2000000
    val = mp.Value('i', 100)
    arr = mp.Array('i', 10)

    p1 = mp.Process(target=func, args=(n, val, lock, True))
    p2 = mp.Process(target=func, args=(n, val, lock, False))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    elapsed = timer() - start
    print("Time elapsed = {}".format(elapsed))
    print(f"Val = {val.value}")

标签: pythonpython-3.xlockingpython-multiprocessingsemaphore

解决方案


推荐阅读