For multi process or multi thread access to shared data, it is often necessary to control the lock in the business layer to increase the brain load. Here, a general way is designed, and the lock operation is directly encapsulated in the data structure. Paste code directly
#!/usr/bin/env python # encoding: utf-8 from multiprocessing import Lock, RLock def make_property(name): try: return prop_cache[name] except KeyError: d = {} exec(template % ((name,) * 7), d) prop_cache[name] = d[name] return d[name] template = ''' def get%s(self): self.acquire() try: return self._obj.%s finally: self.release() def set%s(self, value): self.acquire() try: self._obj.%s = value finally: self.release() %s = property(get%s, set%s) ''' prop_cache = {} class SynchronizedBase(object): def __init__(self, obj, lock=None): self._obj = obj if lock: self._lock = lock else: self._lock = RLock() self.acquire = self._lock.acquire self.release = self._lock.release def __enter__(self): return self._lock.__enter__() def __exit__(self, *args): return self._lock.__exit__(*args) def get_obj(self): return self._obj def get_lock(self): return self._lock def __repr__(self): return '<%s wrapper for %s>' % (type(self).__name__, self._obj) class Synchronized(SynchronizedBase): value = make_property('value') class Obj(object): def __init__(self, value): self.value = value def SafeObj(obj, lock=None): return Synchronized(obj, lock) if __name__ == '__main__': a = SafeObj(Obj(3)) b = SafeObj(Obj(4), Lock()) print(a.value) print(b.value)
SafeObj wraps Obj and returns an object with synchronization primitives. Because it is abstract enough, its access behavior is consistent with that of Obj. The code can also be extended, such as how Synchronized accesses Obj's method.