1つのスレッドでネストされたリストに値を追加し、ネストしたリストをメインスレッドのリスト内包にコピーします。私の例ではスレッドロックを使用する必要がありますか?私はlist.append()
メソッドis thread-safeを知っていますが、リスト内包でデータをコピーするときにロックを使用する必要がありますか?この例ではスレッドロックを使用する必要がありますか?
ロックを使用する必要がある場合、copy_data()
でロックを使用するのは意味がありますが、GrowList._add_to_list()
ではロックされていませんか?
import threading
import time
class GrowList(object):
def __init__(self):
self.data = []
self.stop_event = threading.Event()
self.add_to_list()
def _add_to_list(self):
sample = [1, 2, 3, 4]
while not self.stop_event.is_set():
self.data.append(sample)
time.sleep(1.0)
def add_to_list(self):
self.t = threading.Thread(target=self._add_to_list)
self.t.start()
def stop(self):
self.stop_event.set()
self.t.join()
def copy_data(nested_list):
return [row[:] for row in nested_list]
のように書くことができ、リストの内包表記を可能
__iter__
方法を 。リストの理解の実行が評価されている間に追加の要素が追加される可能性があるので、リストのすべての要素をコピーしないことになります。 CPythonの現在の実装では、リストの末尾に順方向に反復しながら追加すると、通常は期待どおりに動作します。最悪の場合は、予期しないコピー結果(スキップされた要素など)が発生します。 – dhke私の 'copy_data'の必要条件は、関数が呼び出された時点でネストされたリスト内のすべての要素を取り出すことです。コピー中に追加されたアイテムがコピーされなかった場合は問題ありません。この要件を念頭に置いて、ロックを使用しないことは容認できますか? – Jakub
それには保証はありません。 Pythonの保証は、マルチスレッドアクセス中にリストに「ダメージを与える」ことができないことです。つまり、リストの理解中にアイテムが追加されると、リストの内容の一部が取得されます。それが大丈夫なら、GILだけが必要です。それ以外の場合は、ロックを使用します。とにかくGILはそこにあることに注意してください。 – dhke