2014-11-07 1 views
2

Скажите, что метод выглядит так.Нужно ли мне блокировать параллельный метод, который принимает ReadOnlyCollection как параметр?

Class MyClass 
public string ConcatenateList(ReadOnlyCollection<string> aList) 
{ 
    var result = new StringBuilder(); 
    foreach (string s in aList) 
    { 
    result.Append(", " + s); 
    } 
    return result.ToString(); 
} 

Вот пример вызывающей она позволяет список только для чтения, чтобы перейти к MyClass.ConcatenateList методы.

var list = new List<string>(){"hello","world"}; 
var readOnlyList = new ReadOnlyCollection<string>(list); 

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

2 вопросы:

(1) С учетом выше требований, есть состояние гонки в методе? Насколько я вижу, их нет. ThreadA никогда не будет читать или писать в StringBuilder ThreadB, поэтому проблема параллелизма отсутствует и, следовательно, нет необходимости в блокировке. Правда?

(2) Будет ли когда-нибудь случай, когда параллелизм может привести к тому, что возвращаемая строка будет иметь неожиданный результат? Один пример: ThreadA возвращается с «, hello, world, howdy», даже когда «howdy» был добавлен посреди исполнения в список, принадлежащий только ThreadB. Может ли это случиться?

Я пытаюсь понять, учитывая параллелизм, если ConcatenateList() должен быть «чистой функцией», то есть гарантируется, что его параметр «aList» никогда не будет изменен (сам или вызывающий) в течение всего выполнения метода?

Заранее благодарим за мысли!

ответ

3

ReadOnlyCollection не копирует данные в список, предоставленный в конструкторе, в новую коллекцию, которая предоставляет только элементы только для чтения. Вместо этого он просто обертывает предоставленный IList и предоставляет только его члены, доступные только для чтения.

Это означает, что ReadOnlyList обращается к той же самой памяти, к которой обращается исходная ссылка List, и правильная синхронизация должна использоваться, чтобы это было безопасно. В этом примере, поскольку отсутствует синхронизация, изменения в базовом списке вызывающим, в то время как другой поток обращается к списку только для чтения, может вызвать любое количество неопределенных действий.

+1

Возможно также стоит отметить, что даже если исходное _collection_ было неизменным, это не обязательно гарантировало бы, что отдельные _items_ были неизменными (хотя я думаю, что с String они будут), так что было бы что-то еще, чтобы следить для. – paul