python 多进程锁Lock和共享内存

多进程锁

  • lock = multiprocessing.Lock() 创建一个锁

  • lock.acquire() 获取锁

  • lock.release() 释放锁

  • with lock: 自动获取、释放锁 类似于 with open() as f:

  • 特点:

    谁先抢到锁谁先执行,等到该进程执行完成后,其它进程再抢锁执行

  • 当程序不加锁时:

        import multiprocessing
        import time
    
    
        def add(num, value, lock):
            print('add{0}:num={1}'.format(value, num))
            for i in xrange(0, 2):
                num += value
                print('add{0}:num={1}'.format(value, num))
                time.sleep(1)
    
        if __name__ == '__main__':
            lock = multiprocessing.Lock()
            num = 0
            p1 = multiprocessing.Process(target=add, args=(num, 1, lock))
            p2 = multiprocessing.Process(target=add, args=(num, 3, lock))
            p3 = multiprocessing.Process(target=add, args=(num, 5, lock))
    
            p1.start()
            p2.start()
            p3.start()
    
            print('main end...')
    
        # 执行结果:
        add1:num=0
        add1:num=1
        main end...
        add3:num=0
        add3:num=3
        add5:num=0
        add5:num=5
        add3:num=6
        add1:num=2
        add5:num=10
    
        运得没有顺序,三个进程交替运行
  • 当程序加锁时

        import multiprocessing
        import time
    
    
        def add(num, value, lock):
            try:
                lock.acquire()
                print('add{0}:num={1}'.format(value, num))
                for i in xrange(0, 2):
                    num += value
                    print('add{0}:num={1}'.format(value, num))
                    time.sleep(1)
            except Exception as err:
                raise err
            finally:
                lock.release()
    
    
        if __name__ == '__main__':
            lock = multiprocessing.Lock()
            num = 0
            p1 = multiprocessing.Process(target=add, args=(num, 1, lock))
            p2 = multiprocessing.Process(target=add, args=(num, 3, lock))
            p3 = multiprocessing.Process(target=add, args=(num, 5, lock))
    
            p1.start()
            p2.start()
            p3.start()
    
            print('main end...')
    
        # 执行结果:
        add3:num=0
        add3:num=3
        main end...
        add3:num=6
        add1:num=0
        add1:num=1
        add1:num=2
        add5:num=0
        add5:num=5
        add5:num=10
    
        只有当其中一个进程执行完成后,其它的进程才会去执行,且谁先抢到锁谁先执行
    

共享内存

  • agre = multiproessing.Value(type, value) 创建一个共享内存的变量agre

        def Value(typecode_or_type, *args, **kwds):
        '''
        Returns a synchronized shared object
        '''
        from multiprocessing.sharedctypes import Value
        return Value(typecode_or_type, *args, **kwds)   
    

    type 声明共享变量agre的类型

    value 共享变量agre的值

  • agre.value 获取共享变量agre的值

  • arr = muliproessing.Array(type, values) 创建一个共享内存的数组arr

        def Array(typecode_or_type, size_or_initializer, **kwds):
        '''
        Returns a synchronized shared array
        '''
        from multiprocessing.sharedctypes import Array
        return Array(typecode_or_type, size_or_initializer, **kwds)
  • 例子:

import multiprocessing
import time


def add(num, value, lock):
    try:
        lock.acquire()
        print('add{0}:num={1}'.format(value, num.value))
        for i in xrange(0, 2):
            num.value += value
            print('add{0}:num={1}'.format(value, num.value))
            print('-------add{} add end-------'.format(value))

            time.sleep(1)
    except Exception as err:
        raise err
    finally:
        lock.release()


def change(arr):
    for i in range(len(arr)):
        arr[i] = 1


if __name__ == '__main__':
    lock = multiprocessing.Lock()
    num = multiprocessing.Value('i', 0)
    arr = multiprocessing.Array('i', range(10))

    print(arr[:])
    p1 = multiprocessing.Process(target=add, args=(num, 1, lock))
    p3 = multiprocessing.Process(target=add, args=(num, 3, lock))
    p = multiprocessing.Process(target=change, args=(arr,))

    p1.start()
    p3.start()
    p.start()
    p.join()
    print(arr[:])

    print('main end...')
    
执行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
add3:num=0
add3:num=3
-------add3 add end-------
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
main end...
add3:num=6
-------add3 add end-------
add1:num=6
add1:num=7
-------add1 add end-------
add1:num=8
-------add1 add end-------

先执行进程p3并加锁,p3执行过程中进程p执行,因为p没有调用锁且使用了join()方法,阻塞了其它进程,只有当p执行完成后
p3才会继续执行,p3执行完成后,p1抢到锁并执行

p1、p3 都对共享内存num 进行累加操作,所以num的值一直在增加
p 对 arr 共享数组中的每个值进行了重新赋值的操作,所以当P进程执行完成后,arr数组中的值均发生了变化

由上例可以看出:
1、进程锁只对调用它的进程起锁的作用,未调用该锁的进程不受影响
2、在未调用进程锁的进程中使用 join() 方法会阻塞已调用进程锁的进程