通过装饰器对函数加进程锁

通过装饰器对函数加进程锁

发现课程”5-1 进程池与进程锁“中为函数添加进程锁是直接修改函数本身,添加lock.acquire()和lock.release()。如果这个函数是第三方库的,我不想把很长的函数体以及依赖拷贝过来修改原函数呢?可以想到使用装饰器,将进程锁实例存储在函数闭包中访问。
但是主进程并没有阻塞,而是提前执行退出了,能看看原因吗?
执行结果:

(base) bohliu@LM-SHD-16509667 多线程-async % python clipboard.py
main process starts: 84300
execution duration: 0.16681385040283203

完整代码如下:

import os
import time
import random
import multiprocessing


def worker(count):
    print(count, os.getpid())
    sleep = random.randint(1, 3)
    time.sleep(sleep)
    return f"{count} slept for {sleep}, pid: {os.getpid()}"


# decorate the worker function ?
def wrapperLock(worker, lock):
    def help(*args):
        # will not access lock passed as input args to help, but access from closure
        count = args[0]
        if lock:
            lock.acquire()
        res = worker(count, lock)
        if lock:
            lock.release()
        return res
    return help


if __name__ == '__main__':
    print('main process starts:', os.getpid())
    t_start = time.time()
    pool = multiprocessing.Pool(5)
    lock = multiprocessing.Manager().Lock()
    
    workerLock = wrapperLock(worker, lock)
    for i in range(21):
        pool.apply_async(func=workerLock, args=(i,))
    pool.close()
    pool.join()
    
    print('execution duration:', time.time() - t_start)

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学,你好!

以上代码同学的思路不对,同学在调用第三方模块,直接对调用的函数加锁即可,不需要修改原函数,祝学习愉快~

  • 慕莱坞8128705 提问者 #1

    老师您好,我不理解

    1. 课程中演示的对任务函数的加锁过程是:让函数多接收一个锁对象,并在函数体内加上lock.acquire()和lock.release(),这种操作本身就修改了任务函数。如何做到对任务函数不修改而加锁呢?您可以给个代码示例吗?

    2. 我使用装饰器的代码实现中问题出在那里?

    谢谢!

    2022-07-13 06:55:40
  • 好帮手慕凡 回复 提问者 慕莱坞8128705 #2

    同学,你好!

    1、同学直接在调用函数时加锁就可以,不用去修改函数内部,也不用再为第三方模块添加装饰器,调用时加锁即可在不修改函数的情况下进行加锁,可以参考以下代码:

    # coding:utf-8
    
    import os
    import time
    import multiprocessing
    
    def work(count):
    
        print(count, os.getpid())
        time.sleep(1)
    
        return 'result is %s, pid is %s' % (count, os.getpid())
    def wrapperLock(count,lock):
        lock.acquire()
        # 在调用函数时加锁即可
        work(count)
        lock.release()
    
    
    if __name__ == '__main__':
        pool = multiprocessing.Pool(5)
        manger = multiprocessing.Manager()
        lock = manger.Lock()
        results = []
        for i in range(20):
            result = pool.apply_async(func=wrapperLock, args=(i, lock))
            # results.append(result)
    
        # for res in results:
        #     print(res.get())
    
        pool.close()
        pool.join()

    2、使用装饰器并不能起到加锁的作用,help函数并不能被调用,同学可以参考以上代码,在调用时加锁即可在不修改函数的情况下进行加锁

    祝学习愉快~

    2022-07-13 10:02:36
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师