По-перше - більшість класів ніколи не потребуватимуть безпеки. Використовуйте 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
etc для зв'язку між потоками.
Пов'язаний запис у блозі (пізніше переглянуто ).