私の理解には、彼らはしません。ご確認ください。Do lockはリスト要素のスレッド安全を保証しますか?
リストを含むProcessorオブジェクトがあるとします。<T>ここで、Tは参照型です。
UIスレッドはProcessorオブジェクトをインスタンス化し、周期的に呼び出してリストを取得します<T>。
プロセッサオブジェクトは、作成時にリスト<T>への参照を持つタスクも開始します。
ロックは、彼らがリスト<T>への排他的アクセスを確保するためにゲッターで、タスクにT >リスト<へのアクセスを確保するために使用されます。
public class Processor
{
private List<T> _list = new List<T>();
private Object _listLock = new Object();
public Processor()
{
// populate _list
Task t = new Task(Process);
t.Start();
}
public List<T> GetList()
{
lock(_listLock)
{
return _list;
}
}
private void Process()
{
while(!doneProcessing)
{
lock(_listLock)
{
// access and modify _list items
}
Thread.Sleep(...);
}
}
}
しかし、リスト<T>はゲッターにロックされ、そしてそれがロックを捕捉するとき、プロセッサによって開始されたタスクがまだ参照型リスト要素を変更している、問題なくリストの参照が返されても。
リストの要素はプロセッサのタスクから変わる可能性があり、UIスレッドでアクセスするとスレッドセーフではありません。
私が正しいとすれば、明白な解決策は、ゲッターにリスト要素のディープコピーが移入された新しいリストを返すようにすることです。
public List<T> GetList()
{
lock(_listLock)
{
return _list.Select(t => t.Clone()).ToList();
}
}
他に何ができますか?
答えはありませんが、 'ToList()'を呼び出すだけでリストのコピーが作成されます。 – stuartd
リスト全体ではなく、使用している 'List'からメソッドだけを公開することができます。そうすれば、アイテムのアクセスと変更にロックを使用することができます。 –
リストの要素を変更する際に、このようなリストのロックがトレッドセーフティを提供しないという事実を明確にしていますか? – Enigmativity