5

このシングルトン実装を参照してください:</p>

if not hasattr(Singleton, "_instance"):                                    
    with Singleton._instance_lock:                                         
        if not hasattr(Singleton, "_instance"):                            
            Singleton._instance = Singleton()                                 
return Singleton._instance                                      

"Singleton._instance = .."(setattr のようなもの)と hasattr はアトミックのようです。または、setattr が原因で hasattr がクラッシュすることはありません。

しかし、上記の「思われる」をサポートするものは見つかりません。

4

1 に答える 1

6

通常、操作を呼び出すオブジェクトがPython で__getattr____delattr__または__setattr__フックを実装していない場合、はい、、hasattrgetattrはアトミック操作です。delattrsetattr

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(例外のテスト) を使用しgetattr()、Python__getattr__フックを呼び出すことができます。同様に、オペコードは最終的に PythonフックSTORE_ATTRの実装を呼び出す可能性があります。__setattr__どちらの場合も、GIL は再び解放されます。

デフォルトの実装 (Singletonはこれらのフックを実装していません) では、Python C コードが Python にフォールバックすることなく操作全体を処理するため、操作はアトミックです。したがって、評価ループ (GIL が解放され、別のスレッドのために再度ロックされる可能性があります)。

もちろん、オブジェクト プロトコルの操作中にロックを解除するカスタム C ライブラリを扱うこともできます。それは異常なことだろう。

于 2013-06-01T11:33:44.467 に答える