#c#
#c#
Вопрос:
Что не так с этим примером, он выдает ошибку «Метод синхронизации объекта был вызван из несинхронизированного блока кода» на мониторе.PulaseAll(гггг)?
class Program
{
static object yyy = 1;
public static void test(int x)
{
while (true)
{
lock (yyy)
{
Console.WriteLine("T" x.ToString());
while (x != (int)yyy)
{
Monitor.Wait(yyy);
continue;
}
Console.Write(new string(x.ToString()[0], 20));
yyy = 1 (int)yyy;
yyy = ((int)yyy == 4) ? 1 : yyy;
Console.WriteLine("------------------------1--");
Monitor.PulseAll(yyy);
Console.WriteLine("------------------------2--");
}
}
}
public static void Main ()
{
Thread t1 = new Thread(new ThreadStart(() => { test(3);}));
Thread t2 = new Thread(new ThreadStart(() => { test(2);}));
Thread t3 = new Thread(new ThreadStart(() => { test(1);}));
t1.Start();
t2.Start();
t3.Start();
while (true)
Thread.Sleep(500);
}
}
Ответ №1:
Ошибка здесь заключается в изменении объекта блокировки.
Чтобы запустить [все], у вас должна быть блокировка. Похоже, что у вас есть блокировка, но если вы внимательно посмотрите, вы переназначаете yyy
в коде, так что это другой объект.
По этой причине объектами блокировки обычно являются readonly
поля.
Кроме того, блокировка типа значения в штучной упаковке или строки, как правило, является плохой идеей; наиболее подходящим объектом блокировки является:
private readonly object syncLock = new object();
(может быть дополнительно static
при необходимости)
Будучи частным экземпляром, можно избежать неожиданных конфликтов блокировок; beig только для чтения позволяет избежать случайного переназначения.