What is wrong with this example, it throws error "Object synchronization method was called from an unsynchronized block of code" at Monitor.Pula开发者_JAVA百科seAll(yyy) ?
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);
}
}
The error here is changing the lock object.
To Pulse[All] you must have the lock. It looks like you have a lock, but if you look carefully you reassign yyy
in the code, so that is a different object.
For this reason, lock objects are commonly readonly
fields.
Also, locking on a boxed value-type or a string is generally a bad idea; the most appropriate lock object is:
private readonly object syncLock = new object();
(can additionally be static
if needed)
Being a private instance avoids unexpected lock conflicts; beig readonly avoids accidental reassignment.
精彩评论