2017-03-24 7 views
1

asyncio.coroutinesを使用して辞書を管理する単純なPythonプログラムを作成しています。設計は、各コルーチンが異なるキーを持つエントリを辞書に追加するというものです。私の質問は、競合状態を避けるために辞書を変更するときに同期が必要なのですか?言い換えれば、辞書に原子を書き込むのですか?ここでPythonで異なるキーを使用して辞書に同時に書き込む

は私のプログラムです:

map ={} 
key_set = Set(...) 

@asyncio.coroutine 
def update(key): 
    # do I need synchronization here to avoid race condition? 
    map[key] = ... # add a new entry with key to the map 

fut = [] 
for key in key_set: 
    fut.append(update(key)) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(
    asyncio.gather(*fut) 
) 
loop.close() 

答えて

1

はい - 辞書の著作はアトミックです。 asyncioモデルでは、スレッドセーフではなくても、明示的にスレッドプールをどこかで使用している場合を除いて、「実際の並行性」はありません。

Pythonで採用されている非同期モデルの大きな利点は、すべてのI/Oバウンドコードに対して、並列性の複雑さなしに並列性に相当する利点が得られることです.awaitコマンドやその他のコマンドは、あなたの関数コードは他のコードを実行する権利を与えます。つまり、分離が必要な複雑なデータ構造を扱っていても、非同期呼び出しを使わないですべてのコードを中間に置くだけです。

この例では、明示的な一時停止がないので、updateコードは決して別のコルーチンによって中断されません。コルーチンの別のインスタンスによって書き込まれた同じキーを上書きしていないかどうかを確認するためのロジックを追加することもできますが、それでも問題はありません(マルチスレッドコードの場合はロックが必要です)。

@asyncio.coroutine 
def update(key): 
    if key not in map: 
     map[key] = ... # add a new entry with key to the map 
    else: 
     logger.info(f'"{key}" already in use.') 

しかし、コードがマルチスレッドであっても、辞書はPythonでもスレッドセーフです。悪意のあるグローバルインタプリタロック(GIL) - 数十年にわたりPythonを並列コードに戻していたため、トレードオフは辞書やリストなどのデータ構造のスレッドセーフです。

+0

asyncioモデルとGILに関する洞察を深めてくれてありがとう。 –

1

いいえ、asyncioはスレッドを使用しないため、ロックや競合状態を心配する必要はありません。

coroutinesによって提供される並行性は、すべてメインスレッド内で達成されます。

関連する問題