6

あるスレッドで辞書が更新されており、別のスレッドでその値を繰り返し処理したいと思います。通常はロックを使用しますが、このコードはパフォーマンスが非常に重要であり、可能な限りそれを避けたいと思います。

私の場合の特別な特徴は、イテレータの絶対的な正確さを気にしないことです。反復の開始後に削除されたエントリを見逃したり、後で追加されたエントリを取得したりする場合は、問題ありません。「反復中に変更された辞書のサイズ」の例外が発生しないことだけが必要です。

正しさに対するこの緩和された制約を考えると、ロックを使用せずに辞書を反復する効率的な方法はありますか?

注:keys()Python 2.xではスレッドセーフであることは承知していますが、3.xではその動作が変更されているため、回避したいと思います。

4

4 に答える 4

4

これに関する個人的な経験はありませんが、私は少し前にこれを読みました:http ://www.python.org/dev/peps/pep-3106/

これらの操作は、スレッドセーフでない方法で使用すると例外が発生する可能性があるが、内部表現の破損は発生しない範囲でのみ、スレッドセーフです。

Python 2.xと同様に、イテレーターを使用して繰り返しながらdictを変更すると、未定義の効果があり、ほとんどの場合、RuntimeError例外が発生します。(これは、Javaコレクションフレームワークによる保証に似ています。)

于 2012-05-15T15:27:07.607 に答える
3

繰り返したい値を取得するのに十分な長さのロックを使用することを検討します。

with lock:
    values = the_dict.values() # python 2
    # values = list(the_dict.values()) # python 3
for value in values:
    # do stuff

または、ロックとキャッチなしRuntimeErrorで試してみて、取得した場合は、値を再度取得してみてください。

[編集]以下は、JFセバスティアンの提案に従って少し言い換えたものです。

while True:
    try:
        values = list(the_dict.values())
        break
    except RuntimeError:
        pass

私は個人的にロックを持って行きます。

于 2012-05-15T15:15:23.307 に答える
2

2つのこと:

  1. キーをキューにダンプし、安全に読み取ります。
  2. パフォーマンスが重要なコードは、おそらくPythonスレッドを使用してはなりません。
于 2012-05-15T14:56:39.323 に答える
1

言葉よりも例の方が良い場合があります。

配列の反復はスレッドセーフではありません。Python3.6の実際の例を参照してください

于 2019-03-21T10:53:35.813 に答える