Во-первых, _lock
не должен быть статическим.Или вы хотите, чтобы несколько экземпляров объекта блокировали друг друга?Во-вторых, у вас должен быть только один синхронизированный метод в классе.Более того, вам следует избегать зависимостей между синхронизированными методами в вашем классе.В противном случае вы рискуете, что вызывающая сторона ваших методов сделает это неправильно и получит неожиданное поведение.
Рассмотрим, например, этот код:
class Synchronized
{
object lockObj = new object();
int counter = 100;
public void Decrement()
{
lock (this.lockObj)
{
this.counter--;
}
}
public int IsZero()
{
lock (this.lockObj)
{
return this.counter == 0;
}
}
}
Что теперь делатьс совместно используемым экземпляром Synchronized?
Использовать это так
while (!synchronized.IsZero())
{
synchronized.Decrement();
}
Теперь поток 1 вызывает Decrement, счетчик получает значение 0, а поток 2 немедленно вызывает Decrement, потому что он ожидал блокировки в методе Decrement, а не метод IsZero.Счетчик теперь равен -1, а цикл бесконечен.
Дело не в том, что механизм блокировки был неправильно запрограммирован, а в том, что вызывающая сторона не использовала его должным образом.Если вы выставите только один синхронизированный метод в своем классе Synchronized, вы не будете обманывать программиста, слепо полагая, что это безопасно.
Это должно быть примерно так:
class Synchronized
{
object lockObj = new object();
int counter = 100;
public bool IfNotZeroDecrement()
{
lock (this.lockObj)
{
if (this.counter > 0)
this.counter--;
return this.counter > 0;
}
}
}
/// Usage:
while (synchronized.IfZeroDecrement())
{
}