Во-первых - большинству классов никогда не потребуется поточнобезопасность. Использовать YAGNI : применять потокобезопасность только тогда, когда вы знаете, что на самом деле собираетесь его использовать (и тестировать).
Для материала уровня метода есть [MethodImpl]
:
[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}
Это также можно использовать для методов доступа (свойства и события):
private int i;
public int SomeProperty
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return i; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { i = value; }
}
Обратите внимание, что полевые события синхронизируются по умолчанию, в то время как автоматически реализуемые свойства не :
public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized
Лично мне не нравится реализация MethodImpl
, поскольку она блокирует this
или typeof(Foo)
- что противоречит лучшей практике. Предпочтительным вариантом является использование ваших собственных замков:
private readonly object syncLock = new object();
public void SomeMethod() {
lock(syncLock) { /* code */ }
}
Обратите внимание, что для событий типа поля реализация блокировки зависит от компилятора; в старых компиляторах Microsoft это lock(this)
/ lock(Type)
- однако в более поздних компиляторах использует Interlocked
обновлений - поэтому поточно-ориентированные без неприятных деталей.
Это позволяет более детально использовать и позволяет использовать Monitor.Wait
/ Monitor.Pulse
и т. Д. Для связи между потоками.
Связанная запись в блоге (позже вновь ).