def test( users_list, query_times, user_locks, constraints_num,):
Nei = []
manager = multiprocessing.Manager()
query_times = manager.Value('i', query_times)
constraints_num = manager.Value('i', constraints_num)
user_locks = manager.dict({user: manager.Lock() for user in users_list})
print('user_locks',user_locks)
print('users_list',users_list)
print(user_locks[users_list[0]])
运行函数test,结果如下
user_locks {<user object at 0x000001F7A5A40550>: <AcquirerProxy object, typeid 'Lock' at 0x1f7a5f589d0>, <user object at 0x000001F7A5F58C50>: <AcquirerProxy object, typeid 'Lock' at 0x1f7a5f58d50>, }
users_list [<user object at 0x0000025AE8A7AB90>, <user object at 0x0000025AE8329750>, ]
Traceback (most recent call last):
KeyError: <user object at 0x0000025AE8A95890>
分析:
问题仍然在于 user_locks 的键值访问。尽管你已经通过 multiprocessing.Manager 创建了共享字典 user_locks,但访问时仍然出现了 KeyError。这表明 users_list 中的 user 对象和 user_locks 字典中的键不匹配。
问题分析
对象引用不一致:
在多进程环境中,multiprocessing.Manager 会通过代理机制(proxy)来管理共享对象。这意味着 user 对象在不同进程中的引用可能不一致。
你在 users_list 中的 user 对象和 user_locks 字典中的键可能不是同一个对象,即使它们逻辑上是相同的。
user 对象的唯一性:
user 对象的内存地址(如 0x000001F7A5A40550 和 0x0000025AE8A95890)表明它们是不同的实例。即使它们的属性可能相同,但作为字典的键时,它们被视为不同的对象。
multiprocessing.Manager 的代理机制:
multiprocessing.Manager 的代理机制可能会导致对象的引用在不同进程间发生变化。因此,直接使用对象作为字典的键可能会导致问题。
解决方案
为了避免这种问题,建议使用 唯一标识符(如 user.id 或其他属性)作为字典的键,而不是直接使用对象本身。这样可以确保键的唯一性和一致性。
修改代码
以下是修改后的代码示例:
def test( users_list, query_times, user_locks, constraints_num,):
Nei = []
manager = multiprocessing.Manager()
query_times = manager.Value('i', query_times)
constraints_num = manager.Value('i', constraints_num)
# 使用用户的唯一标识符(如 user.id)作为字典的键
user_locks = manager.dict({user.id: manager.Lock() for user in users_list})
print('user_locks', user_locks)
print('users_list', users_list)
# 使用 user.id 访问锁
print(user_locks[users_list[0].id])