-1

当我学习使用SyncManager在多个进程之间共享公共对象时,我注意到Thread在SyncManager的上下文中工作的奇怪行为。

据我了解,SyncManager创建一个服务器进程,接受来自其他进程的连接,然后使用Thread调用目标方法。(https://github.com/python/cpython/blob/master/Lib/multiprocessing/managers.py#L184

但是,在下面的示例代码中,通过调用获得的线程 idthreading.get_ident()结果是相同的值。

我添加了被调用方法的RLock版本以及非锁定版本。从我从日志的时间线中可以看出,它的行为符合预期 - 不同的线程调用该cube方法,但是相同的线程 id 怎么来的?

我了解在最后一个线程终止后,另一个线程中可能会出现相同的线程 ID。但它不能解释没有RLock的行为。

from multiprocessing import Process
from multiprocessing.managers import SyncManager
import time
import os
import logging
import threading
from threading import RLock


class MyManager(SyncManager):
    pass


class CommonObj:
    def __init__(self):
        self.logger = logging.getLogger(
            "COMMON-%d-%d" % (os.getpid(), threading.get_ident())
        )
        self.lock = RLock()

    def cube_lock(self, x):
        with self.lock:
            self.logger.info("lock acquired")
            time.sleep(3)
            result = x * x * x
        self.logger.info("lock released")
        return result

    def cube(self, x):
        self.logger.info("cube called")
        time.sleep(3)
        result = x * x * x
        self.logger.info("cube finish")
        return result


def worker(cube):
    logger = logging.getLogger("WORKER-%d" % os.getpid())
    logger.info("calling common_obj.cube")
    result = cube(2)
    logger.info("result is %d" % result)


def main():
    logging.basicConfig(level=logging.INFO)
    MyManager.register("CommonObj", CommonObj)
    processes = list()
    with MyManager() as manager:
        common_obj = manager.CommonObj()
        print("Calling cube without RLock:")
        for i in range(3):
            p = Process(target=worker, args=(common_obj.cube,))
            processes.append(p)
            p.start()

        for p in processes:
            p.join()
            print("joined %r" % p)

        print("\n\nCalling cube with RLock:")
        processes.clear()
        for i in range(3):
            p = Process(target=worker, args=(common_obj.cube_lock,))
            processes.append(p)
            p.start()

        for p in processes:
            p.join()
            print("joined %r" % p)


if __name__ == "__main__":
    main()

Calling cube without RLock:
INFO:WORKER-1389:calling common_obj.cube
INFO:WORKER-1390:calling common_obj.cube
INFO:COMMON-1388-123145579134976:cube called
INFO:COMMON-1388-123145579134976:cube called
INFO:WORKER-1391:calling common_obj.cube
INFO:COMMON-1388-123145579134976:cube called
INFO:COMMON-1388-123145579134976:cube finish
INFO:COMMON-1388-123145579134976:cube finish
INFO:WORKER-1389:result is 8
INFO:COMMON-1388-123145579134976:cube finish
INFO:WORKER-1391:result is 8
INFO:WORKER-1390:result is 8
joined <Process(Process-2, stopped)>
joined <Process(Process-3, stopped)>
joined <Process(Process-4, stopped)>


Calling cube with RLock:
INFO:WORKER-1394:calling common_obj.cube
INFO:COMMON-1388-123145579134976:lock acquired
INFO:WORKER-1395:calling common_obj.cube
INFO:WORKER-1396:calling common_obj.cube
INFO:COMMON-1388-123145579134976:lock released
INFO:COMMON-1388-123145579134976:lock acquired
INFO:WORKER-1394:result is 8
joined <Process(Process-5, stopped)>
INFO:COMMON-1388-123145579134976:lock released
INFO:COMMON-1388-123145579134976:lock acquired
INFO:WORKER-1395:result is 8
joined <Process(Process-6, stopped)>
INFO:COMMON-1388-123145579134976:lock released
INFO:WORKER-1396:result is 8
joined <Process(Process-7, stopped)>
4

1 回答 1

0

哎呀,宣布记录器__init__,我需要一些睡眠。

于 2020-03-01T15:19:47.417 回答