from threading import RLock _locks = {} def lock_for_object(obj, locks=_locks): return locks.setdefault(id(obj), RLock()) def synchronized(call): def inner(*args, **kwds): with lock_for_object(call): return call(*args, **kwds) return inner