看这个单例实现:
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton()
return Singleton._instance
看来“Singleton._instance = ..”(类似于setattr)和hasattr是原子的。
或者hasattr不会因为setattr而导致崩溃。
但我找不到任何支持上述“似乎”的内容。
Usually,前提是您调用操作的对象没有实现__getattr__ http://docs.python.org/2/reference/datamodel.html#object.__getattr__, __delattr__ http://docs.python.org/2/reference/datamodel.html#object.__detattr__ or __setattr__ http://docs.python.org/2/reference/datamodel.html#object.__setattr__python 中的钩子,那么是的,hasattr
, getattr
, delattr
and setattr
是原子操作。
就 Python 线程而言,任何单独的字节码都是原子操作。 Python 求值循环在解释操作码时获取全局解释器锁 (GIL)。
您需要查看字节码才能了解边界在哪里:
>>> def foo():
... if not hasattr(Singleton, "_instance"):
... with Singleton._instance_lock:
... if not hasattr(Singleton, "_instance"):
... Singleton._instance = Singleton()
... return Singleton._instance
...
>>> dis.dis(foo)
2 0 LOAD_GLOBAL 0 (hasattr)
3 LOAD_GLOBAL 1 (Singleton)
6 LOAD_CONST 1 ('_instance')
9 CALL_FUNCTION 2
12 POP_JUMP_IF_TRUE 64
3 15 LOAD_GLOBAL 1 (Singleton)
18 LOAD_ATTR 2 (_instance_lock)
21 SETUP_WITH 35 (to 59)
24 POP_TOP
4 25 LOAD_GLOBAL 0 (hasattr)
28 LOAD_GLOBAL 1 (Singleton)
31 LOAD_CONST 1 ('_instance')
34 CALL_FUNCTION 2
37 POP_JUMP_IF_TRUE 55
5 40 LOAD_GLOBAL 1 (Singleton)
43 CALL_FUNCTION 0
46 LOAD_GLOBAL 1 (Singleton)
49 STORE_ATTR 3 (_instance)
52 JUMP_FORWARD 0 (to 55)
>> 55 POP_BLOCK
56 LOAD_CONST 0 (None)
>> 59 WITH_CLEANUP
60 END_FINALLY
61 JUMP_FORWARD 0 (to 64)
6 >> 64 LOAD_GLOBAL 1 (Singleton)
67 LOAD_ATTR 3 (_instance)
70 RETURN_VALUE
故事并没有结束;hasattr
uses getattr()
(测试异常),这又可以调用Python__getattr__
钩。同样,STORE_ATTR
操作码最终可能会调用 python__setattr__
钩子实现。在这两种情况下,GIL 都会被再次释放。
对于默认实现(Singleton
没有实现这些钩子)操作是原子的,因为 Python C 代码处理整个操作,而不会回退到 Python,因此不会回退到评估循环(其中 GIL 可能会被释放并再次锁定另一个线程)。
当然,您仍然可以使用自定义 C 库来释放锁对象协议操作 http://docs.python.org/2/c-api/object.html。这将是一件不寻常的事情。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)