开发者

Monitor.PulaseAll throws error

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜