【问题标题】:Python - How to use multiprocessing Lock in class instance?Python - 如何在类实例中使用多处理锁?
【发布时间】:2018-11-01 06:44:31
【问题描述】:

我在 Windows 上使用 Python 3.7。

我正在尝试做的事情: - 当另一个进程获得相同的锁时,锁定一个类实例的方法。

尝试:

我已经成功地完成了this,但我不想要一个全局变量用于锁,而是一个完全在类内部的变量

from multiprocessing import Lock, freeze_support,Pool
from time import sleep

def do_work(name):
    print(name+' waiting for lock to work...',end='')
    sleep(2)
    with lock:
        print('done!')
        print(name+' doing work...',end='')
        sleep(5)
        print('done!')

def init(olock):
    global lock
    lock = olock

if __name__ == '__main__':
    freeze_support()
    args_list = [('a'),('b'),('c')]
    lock=Lock()
    p=Pool(8,initializer=init,initargs=(lock,))
    p.map_async(do_work,args_list)
    p.close()
    p.join()

当最后一段代码运行时,由于锁定,它需要 ~17.3 秒。没有锁需要 ~7 秒

我试图在一个类中实现这个,但是锁什么也不做,它总是在 ~7 秒内运行

class O():
    def __init__(self):
        self.lock=Lock()
    def __getstate__(self): # used to remove multiprocess object(s) from class, so it can be pickled
        self_dict=self.__dict__.copy()
        del self_dict['lock']
        return self_dict
    def __setstate__(self,state): # used to remove multiprocess object(s) from class, so it can be pickled
        self.__dict__.update(state)
    def _do_work(self,name):
        print(name+' waiting for lock to work...',end='')
        sleep(2)
        with self.lock:
            print('done!')
            print(name+' doing work...',end='')
            sleep(5)
            print('done!')

if __name__ == '__main__':
    freeze_support()
    c = O()
    pool = Pool(8)
    pool.apply_async(c._do_work,('a',))
    pool.apply_async(c._do_work,('b',))
    pool.apply_async(c._do_work,('c',))
    pool.close()
    pool.join()

问题: 那么,当我调用一个通过多处理与资源异步交互的方法时,我该怎么做才能锁定这个类实例呢?

【问题讨论】:

    标签: python-3.x locking python-multiprocessing python-3.7


    【解决方案1】:

    apply_async 会pickle 函数对象并通过队列发送到pool worker 进程,但由于c._do_work 是绑定方法,实例也会被pickle,从而导致错误。你可以把它包装在一个普通的函数中:

    c = O()
    def w(*args):
        return c._do_work(*args)
    
    if __name__ == '__main__':
        pool = Pool(1)
        pool.apply_async(w, ('a',))
        ...
    

    你应该删除__setstate__/__getstate__

    【讨论】:

      猜你喜欢
      • 2021-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多