Locking でアトミック カウンターを使用する必要がありますか、それともこれを使用できますか?
def somefunc(someparam):
if someparam:
dic['key'] +=1
Locking でアトミック カウンターを使用する必要がありますか、それともこれを使用できますか?
def somefunc(someparam):
if someparam:
dic['key'] +=1
いいえ、あなたのコードはスレッドセーフではありません。+=
ディクショナリ値で拡張割り当てを使用すると、実行に 3 つのオペコードが必要になるためです。
>>> dis.dis(compile("dic['key'] += 1", '', 'exec'))
1 0 LOAD_NAME 0 (dic)
3 LOAD_CONST 0 ('key')
6 DUP_TOPX 2
9 BINARY_SUBSCR
10 LOAD_CONST 1 (1)
13 INPLACE_ADD
14 ROT_THREE
15 STORE_SUBSCR
16 LOAD_CONST 2 (None)
19 RETURN_VALUE
位置 9 のオペコードはBINARY_SUBSCR
、ディクショナリから現在の値を取得します。STORE_SUBSCR
オペコード 9 と 15 の間 (値を戻す場所) のどこでも、スレッド切り替えが発生し、別のスレッドが辞書を更新した可能性があります。
Python の組み込み構造は、単一操作に対してスレッド セーフです。GIL (グローバル インタープリター ロック) がそれを処理します。しかし、ステートメントがより多くの操作になる場所を確認することはほとんどの場合困難です。
ロックを追加すると安心できます。
def somefunc(someparam):
if someparam:
with lock:
dic['key'] +=1