首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >getattr/setattr/hasattr/delattr线程安全吗?

getattr/setattr/hasattr/delattr线程安全吗?
EN

Stack Overflow用户
提问于 2013-06-01 19:29:33
回答 1查看 1.6K关注 0票数 4

请参阅此Singleton实现:

代码语言:javascript
复制
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而导致崩溃。

但我找不到任何东西来支持上面的“似乎”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-01 19:33:44

通常是,如果你调用操作的对象没有在python中实现__getattr____delattr____setattr__挂钩,那么是的,hasattrgetattrdelattrsetattr都是原子操作。

就Python线程而言,任何单个字节码都是原子操作。Python求值循环在解释操作码时获取全局解释器锁(GIL)。

您需要查看字节码以了解边界所在:

代码语言:javascript
复制
>>> 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使用getattr() (测试异常),它反过来可以调用Python __getattr__钩子。类似地,python操作码可能最终调用一个STORE_ATTR __setattr__挂钩实现。在这两种情况下,GIL都会再次释放。

对于默认实现(Singleton不实现这些钩子),操作是原子的,因为Python C代码处理整个操作,而不会退回到Python,从而导致计算循环(在那里,GIL可能会被释放并为另一个线程再次锁定)。

当然,您仍然可以处理在object protocol operations期间释放锁的自定义C库。这将是一件不寻常的事情。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16872210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档