Python多进程编程之进程锁Lock

by LauCyun Aug 19,2016 17:33:03 20,816 views

当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突。

1 不加进程锁

让我们看看没有加进程锁时会产生什么样的结果。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import multiprocessing
import time


def job(val, num):
    for _ in range(5):
        time.sleep(0.1)  # 暂停0.1秒,让输出效果更明显
        val.value += num  # val.value获取共享变量值
        print(val.value)


def multicore():
    val = multiprocessing.Value('i', 0)  # 定义共享变量
    p1 = multiprocessing.Process(target=job, args=(val, 1))
    p2 = multiprocessing.Process(target=job, args=(val, 3))  # 设定不同的number看如何抢夺内存
    p1.start()
    p2.start()
    p1.join()
    p2.join()


if __name__ == '__main__':
    multicore()

在上面的代码中,我们定义了一个共享变量val,两个进程都可以对它进行操作。 在job()中我们想让val每隔0.1秒输出一次累加num的结果,但是在两个进程p1p2 中设定了不同的累加值。所以接下来让我们来看下这两个进程是否会出现冲突。

运行一下:

3
4
7
8
11
12
15
16
19
20

我们可以看到,进程1和进程2在相互抢着使用共享内存val

2 进程锁

为了解决上述不同进程抢共享资源的问题,我们可以用加进程锁Lock来解决。

首先需要定义一个进程锁

lock = multiprocessing.Lock()  # 定义一个进程锁

然后将进程锁的信息传入各个进程中

p1 = multiprocessing.Process(target=job, args=(val, 1, lock))  # 需要将Lock传入
p2 = multiprocessing.Process(target=job, args=(val, 3, lock))  # 设定不同的number看如何抢夺内存

job()中设置进程锁的使用,保证运行时一个进程的对锁内内容的独占

def job(val, num, lock):
    lock.acquire()  # 锁住
    for _ in range(5):
        time.sleep(0.1)  # 暂停0.1秒,让输出效果更明显
        val.value += num  # val.value获取共享变量值
        print(val.value)
    lock.release()  # 释放

完整代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import multiprocessing
import time


def job(val, num, lock):
    lock.acquire()  # 锁住
    for _ in range(5):
        time.sleep(0.1)  # 暂停0.1秒,让输出效果更明显
        val.value += num  # val.value获取共享变量值
        print(val.value)
    lock.release()  # 释放


def multicore():
    val = multiprocessing.Value('i', 0)  # 定义共享变量
    lock = multiprocessing.Lock()  # 定义一个进程锁
    p1 = multiprocessing.Process(target=job, args=(val, 1, lock))  # 需要将Lock传入
    p2 = multiprocessing.Process(target=job, args=(val, 3, lock))  # 设定不同的number看如何抢夺内存
    p1.start()
    p2.start()
    p1.join()
    p2.join()


if __name__ == '__main__':
    multicore()

运行一下,让我们看看是否还会出现抢占资源的情况:

1
2
3
4
5
8
11
14
17
20

显然,进程锁保证了进程p1的完整运行,然后才进行了进程p2的运行

Tags