Является ли свойство List <T>потокобезопасным? - PullRequest
3 голосов
/ 03 мая 2011
    private List<T> _T;
    private readonly object _syncLock = new object();

    private List<T> MyT
    {
        get
        {
            lock (_syncLock)
                return _T.ToList<T>();
        }
        set
        {
            lock (_syncLock)
                _T = value;
        }
    }

Ответы [ 3 ]

2 голосов
/ 04 мая 2011

Нет, это не потокобезопасно. Посмотрите на следующий код:

static MyClass<int> sharedInstance = ...;

// Create a list
var list = new List<int>();

// Share the list
sharedInstance.MyT = list;

// list is now shared, this call is not thread-safe.
list.Add(5);

Проблема в том, что вы позволяете потребителям иметь ссылку на внутреннюю структуру данных. Вы можете решить эту проблему следующим образом:

private List<T> MyT
{
    get
    {
        lock (_syncLock)
            return _T.ToList<T>();
    }
    set
    {
        var copy = value.ToList();

        lock (_syncLock)
            _T = copy;
    }
}
2 голосов
/ 03 мая 2011

Да. Вы использовали переменную-член в качестве блокировки и убедились, что она не может быть изменена. Это будет хорошо работать.

1 голос
/ 03 мая 2011

Да, вы в безопасности.Если вы посмотрите на определение ToList (), то это:

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return new List<TSource>(source);
}

Итак, по сути, вы создаете новый список, который содержит элементы старого списка, все под блокировкой, которую вы предоставляете, что обеспечивает безопасность потока.,

Теперь СОДЕРЖАНИЕ списка будет одинаковыми ссылками в обоих списках, поэтому оно не защитит вас от изменения оригинальных объектов, хранящихся в списке, а только самого списка.

...