Monitor.PulaseAll抛出错误

时间:2011-05-04 15:23:41

标签: c#

这个例子有什么问题,它会在Monitor.PulaseAll(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);
    }
}

1 个答案:

答案 0 :(得分:6)

此处的错误是 更改锁定对象

To Pulse [All]你必须拥有锁。 看起来就像你有一个锁,但如果你仔细看,你在代码中重新分配yyy,这是一个不同的对象

出于这个原因,锁定对象通常是readonly字段。

此外,锁定盒装值类型或字符串通常是一个坏主意;最合适的锁定对象是:

private readonly object syncLock = new object();

(如果需要,还可以static

作为私有实例可以避免意外的锁定冲突; beig readonly避免意外重新分配。