Часто, когда я хочу класс, который является потокобезопасным, я делаю что-то вроде следующего:
public class ThreadSafeClass
{
private readonly object theLock = new object();
private double propertyA;
public double PropertyA
{
get
{
lock (theLock)
{
return propertyA;
}
}
set
{
lock (theLock)
{
propertyA = value;
}
}
}
private double propertyB;
public double PropertyB
{
get
{
lock (theLock)
{
return propertyB;
}
}
set
{
lock (theLock)
{
propertyB = value;
}
}
}
public void SomeMethod()
{
lock (theLock)
{
PropertyA = 2.0 * PropertyB;
}
}
}
Это работает, но это очень много. Иногда я даже создаю объект блокировки для каждого метода и свойства, создавая большую детализацию и сложность.
Я знаю, что также можно блокировать классы, используя атрибут Synchronization, но я не уверен, насколько хорошо эти масштабы - поскольку я часто ожидаю иметь сотни тысяч, если не миллионы, экземпляров потокобезопасных объектов, Этот подход создавал бы контекст синхронизации для каждого экземпляра класса и требовал, чтобы класс был выведен из ContextBoundObject и поэтому не мог быть получен из чего-либо другого - поскольку С# не допускает множественного наследования - это шоу-стоппер во многих случаях.
Изменить: как подчеркнули некоторые из респондентов, нет никакой концепции создания "потоковой безопасности" с "серебряной пулей". Я просто пытаюсь понять, является ли шаблон, который я использую, одним из хороших решений. Конечно, лучшее решение в любой конкретной ситуации зависит от проблемы. Некоторые из приведенных ниже ответов содержат альтернативные варианты, которые следует учитывать.
Изменить: Кроме того, существует более одного определения безопасности потоков. Например, в моей реализации выше, следующий код НЕ был бы потокобезопасным:
var myObject = new ThreadSafeClass();
myObject.PropertyA++; // NOT thread-safe
Итак, действительно ли определение класса представляет собой хороший подход? Если нет, что бы вы порекомендовали для дизайна с аналогичным поведением, которое было бы потокобезопасным для аналогичного набора применений?