Python中使用多进程模块时无法进行进程间互锁

4

我是一个对Python比较新的人。我一直在学习和研究多进程模块,但在使用锁时遇到了困难。

这里是测试代码:

import multiprocessing
from multiprocessing import Pool

class Param_Class():

#Initialisation.
    def __init__(self):
        self.counter = multiprocessing.Value('i',0)
        self.lock = multiprocessing.Lock()

    def inc_counter(self):
            lk.acquire()
            print('Locked {}'.format(multiprocessing.current_process().name))
            self.counter.value+=1
            lk.release()
            print('Released {}'.format(multiprocessing.current_process().name))

param_class = Param_Class()

def init(lock):
    global lk
    lk = lock


def target():
    param_class.inc_counter()
    code = 0
    return code

def handler(i):
    if i<50:
        code = target()
        print(param_class.counter.value)


if __name__ == '__main__':
    p = Pool(processes=2,initializer=init, initargs=(param_class.lock,))
    p.map_async(handler,range(50))
    p.close()
    p.join()

我希望的是每个进程在执行时都被锁定,这样我的计数器应该在任何一个进程被执行时递增。然而,进程之间没有互锁,第二个进程正在使用计数器的副本。
以下是输出:
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
1
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
2
Released SpawnPoolWorker-2
1
Locked SpawnPoolWorker-1
Locked SpawnPoolWorker-2
Released SpawnPoolWorker-1
Released SpawnPoolWorker-2
3
2
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
4
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
3
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
5
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
4
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
6
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
5
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
7
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
6
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
8
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
7
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
9
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
8
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
10
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
9
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
11
Released SpawnPoolWorker-2
10
Locked SpawnPoolWorker-1
Locked SpawnPoolWorker-2
Released SpawnPoolWorker-1
Released SpawnPoolWorker-2
12
11
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
13
Released SpawnPoolWorker-2
12
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
14
Released SpawnPoolWorker-2
13
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
15
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
14
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
16
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
15
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
17
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
16
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
18
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
17
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
19
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
18
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
20
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
19
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
21
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
20
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
22
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
21
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
23
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
22
Released SpawnPoolWorker-1
24
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
25
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
26
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
27
Locked SpawnPoolWorker-1
Released SpawnPoolWorker-1
28

期望的输出应该类似于这样:

Locked SpawnPoolWorker-1
1
Released SpawnPoolWorker-1
Locked SpawnPoolWorker-2
2
Released SpawnPoolWorker-2
Locked SpawnPoolWorker-1
3
Released SpawnPoolWorker-1
.
.
.
.
.
.
.
Locked SpawnPoolWorker-2
50
Released SpawnPoolWorker-2

我参考了 这个页面 来了解如何初始化锁并继承它。我无法理解我哪里出了错。是锁、multiprocessing.Pool 调用或使用类实例或目标函数本身的问题。请详细说明,并支持一些理论。我想学习这个,而不仅仅是解决它。
注意,在获得的输出中,从值24到28按预期工作,进程2停止工作。需要对此进行澄清。
附:我想避免使用管理器,因为像链接中提到的那样,管理器很重量级。另外,我不想消除部分并发执行,因为我将使用其他不需要锁定的变量,并且希望该模块保持快速和pythonic。
1个回答

2

显然,每次进程进行应用程序操作时,都会调用类的init方法,因此为每个进程创建一个副本。

因此,为了解决这个问题,可以将计数器作为类属性创建的方式改为在池的初始化中传递并全局使用。

此外,锁定是无关紧要的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接