0%

python | 多进程锁的同步

这里说一下多进程加锁后,程序是怎么样执行的。

多进程主要是充分利用多 CPU 。那么,如果,多个进程修改同一个变量,那么,势必会对这个变量加锁,加锁后,执行顺序会是怎么样?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import os
import time
from multiprocessing import Process, Value


def job(v):
with v.get_lock():
for i in range(10):
time.sleep(0.1)
v.value += i
print(f"{os.getpid()} {v.value}")


if __name__ == '__main__':
v = Value("i", 0)

p1 = Process(target=job, args=(v,))
p2 = Process(target=job, args=(v,))

p1.start()
p2.start()

p1.join()
p2.join()

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
87808 0
87808 1
87808 3
87808 6
87808 10
87808 15
87808 21
87808 28
87808 36
87808 45
87809 45
87809 46
87809 48
87809 51
87809 55
87809 60
87809 66
87809 73
87809 81
87809 90

很明显上述加锁方式,让多进程成为串行数据。

那么,怎么优化呢?

假设 time.sleep 是一种 CPU 密集的活动,那么,我们是不是只需要对数据的存储进行加密,不就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import copy
import os
import time
from multiprocessing import Process, Value


def job(v):
for i in range(10):
tmp = 0
with v.get_lock():
tmp = copy.copy(v.value)
time.sleep(0.1)
tmp += i
with v.get_lock():
v.value = tmp
print(f"{os.getpid()} {v.value}")


if __name__ == '__main__':
v = Value("i", 0)

p1 = Process(target=job, args=(v,))
p2 = Process(target=job, args=(v,))

p1.start()
p2.start()

p1.join()
p2.join()

最后的输出

87135 45

也就是 v.value45,这个和正确的数值 90 有出入。

请我喝杯咖啡吧~