Python对进程/线程锁的一些理解

2018-12-16  本文已影响0人  曲谐_

看multiprocessing部分的Python文档,一点思考:
https://www.rddoc.com/doc/Python/3.6.0/zh/library/multiprocessing/#module-multiprocessing
离职啦,感觉一直拖拖拖,现在反而清醒轻松了不少,开始疯狂产出吧~


from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    try:
        print('hello world', i)
    finally:
        l.release()

if __name__ == '__main__':
    lock = Lock()

    for num in range(10):
        Process(target=f, args=(lock, num)).start()

这里给进程设置了一个进程锁lock。lock在不同进程使用同一共享内存时,能够确保线程之间互不影响,使用lock的方法是, 在每个线程/进程使用共享内存资源或修改共享内存之前,执行lock.acquire()将共享内存上锁, 确保当前进程执行时,内存不会被其他进程访问,执行运算完毕后,使用lock.release()将锁打开, 保证其他的线程可以使用该共享内存。
看似这样做,进程就会输出0-9了,但实际上并不会。

# output result
hello world 0
hello world 1
hello world 5
hello world 2
hello world 4
hello world 7
hello world 3
hello world 6
hello world 8
hello world 9

可见,第一个进程必然是0,这毫无疑问,但后面却散乱排布。这与使用锁的初衷相违背,这是为什么呢?
思考后发现,在第一个进程执行的过程中,即i=0时,它拥有当前的lock,因此它必然是先执行的。但是由于进程是非阻塞的,因此在执行Process的过程中,还是可以继续迭代的,即num=1,2,...,9这个过程中他们都有可能进入Process这一步,等待num=0时执行函数结束,获得当前的Process,因此后面的顺序是不可控的。
如果想要按顺序排布,可以将进程设置为阻塞的。即当前进程执行完之前,后面的进程会先挂起。这可以通过join()函数来实现。

# blocking
from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    try:
        print('hello world', i)
    finally:
        l.release()

if __name__ == '__main__':
    lock = Lock()

    for num in range(10):
        p = Process(target=f, args=(lock, num))
        p.start()
        p.join()

输出结果为:

# output result
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 7
hello world 8
hello world 9
上一篇下一篇

猜你喜欢

热点阅读