static void Main(string[] args)
        {
            Thread PT = new Thread(new ThreadStart(Producer));
            Thread CT = new Thread(new ThreadStart(Consumer));
            PT.Start();
            CT.Start();
            Thread.Sleep(1000);//等待2個線程完成
            Console.WriteLine(value);
        }        static int value = 0;
        static bool[] flag = { false, false };
        static int turn = 0;        static void Producer()
        {
            for (int i = 0; i != 100000; ++i)
            {
                flag[0] = true;
                turn = 1;
                while (flag[1] && turn==1)
                    ;
                ++value;//臨界區
                flag[0] = false;
            }
        }        static void Consumer()
        {
            for (int i = 0; i != 100000; ++i)
            {
                flag[1] = true;
                turn = 0;
                while (flag[0] && turn == 0)
                    ;
                --value;//臨界區
                flag[1] = false;
            }
        }
    }
如果這兩個線程互斥,最后value值應為0.
但運行結果是,value不一定是0.
PS:請不要告訴我"使用lock"之類的辦法.我正在學<<操作系統概念>>中"進程同步"一章,希望自己實現對臨界區加鎖.

解决方案 »

  1.   

    楼主手法相当巧妙啊,学习了。好像
    在两个线程里分别加上这么一句:结果应该是0吧?if (turn == 0)
    {
        turn = 1;
    }
    if (turn == 1)
    {
        turn = 0;
    }
      

  2.   


    //对value的操作改成Interlocked.Increment试试.
            static void Main(string[] args)
            {
                Thread PT = new Thread(new ThreadStart(Producer));
                Thread CT = new Thread(new ThreadStart(Consumer));
                PT.Start();
                CT.Start();
                Thread.Sleep(1000);//等待2個線程完成
                Console.WriteLine(value);
            }        static int value = 0;
            static bool[] flag = { false, false };
            static int turn = 0;        static void Producer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[0] = true;
                    turn = 1;
                    while (flag[1] && turn==1)
                        ;
                    //++value;//臨界區
                    System.Threading.Interlocked.Increment(ref value);
                    flag[0] = false;
                }
            }        static void Consumer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[1] = true;
                    turn = 0;
                    while (flag[0] && turn == 0)
                        ;
                    //--value;//臨界區
                    System.Threading.Interlocked.Decrement(ref value);
                    flag[1] = false;
                }
            }
        }
      

  3.   

    Interlocked.Increment是原子操作,使用Interlocked.Increment根本就不需要鎖住臨界區了.
    而我是要自己實現對臨界區加鎖.
      

  4.   

    幾個有趣的測試結果:
    不加鎖,最終結果往往為幾千到幾萬:
            static void Main(string[] args)
            {
                Thread PT = new Thread(new ThreadStart(Producer));
                Thread CT = new Thread(new ThreadStart(Consumer));
                PT.Start();
                CT.Start();
                Thread.Sleep(1000);//等待2個線程完成
                Console.WriteLine(value);
            }        static int value = 0;        static void Producer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    ++value;//臨界區
                }
            }        static void Consumer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    --value;//臨界區
                }
            }
    像頂樓那樣不成功的加鎖,結果通常為幾十到幾百:
            static void Main(string[] args)
            {
                Thread PT = new Thread(new ThreadStart(Producer));
                Thread CT = new Thread(new ThreadStart(Consumer));
                PT.Start();
                CT.Start();
                Thread.Sleep(1000);//等待2個線程完成
                Console.WriteLine(value);
            }        static int value = 0;
            static bool[] flag = { false, false };
            static int turn = 0;        static void Producer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[0] = true;
                    turn = 1;
                    while (flag[1] && turn==1)
                        ;
                    ++value;//臨界區
                    flag[0] = false;
                }
            }        static void Consumer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[1] = true;
                    turn = 0;
                    while (flag[0] && turn == 0)
                        ;
                    --value;//臨界區
                    flag[1] = false;
                }
            }
        }
    稍微改變一下加鎖的方式,結果大部分時候為0,偶然為1或2:
            static void Main(string[] args)
            {
                Thread PT = new Thread(new ThreadStart(Producer));
                Thread CT = new Thread(new ThreadStart(Consumer));
                PT.Start();
                CT.Start();
                Thread.Sleep(1000);//等待2個線程完成
                Console.WriteLine(value);
            }        static int value = 0;
            static bool flag0 = false;
            static bool flag1 = false;
            static int turn = 0;        static void Producer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag0 = true;
                    turn = 1;
                    while (flag1 && turn==1)
                        ;
                    ++value;//臨界區
                    flag0 = false;
                }
            }        static void Consumer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag1 = true;
                    turn = 0;
                    while (flag0 && turn == 0)
                        ;
                    --value;//臨界區
                    flag1 = false;
                }
            }
      

  5.   

    顶楼的flag是一个变量
    上面这个是2个变量,几率是要小点
      

  6.   

    static void Main(string[] args)
            {
                Thread PT = new Thread(new ThreadStart(Producer));
                Thread CT = new Thread(new ThreadStart(Consumer));
                PT.Start();
                CT.Start();
                Thread.Sleep(1000);//等待2個線程完成
                Console.WriteLine(value);
            }        static int value = 0;
            static bool[] flag = { false, false };
            static int turn = 0;        static void Producer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[0] = true;
                    if (turn == 0) 
                    { 
                       turn = 1; 
                    } 
                    while (flag[1] && turn==1)
                        ;
                    ++value;//臨界區
                    flag[0] = false;
                }
            }        static void Consumer()
            {
                for (int i = 0; i != 100000; ++i)
                {
                    flag[1] = true;
                    if (turn == 1) 
                    { 
                       turn = 0; 
                    }
                    while (flag[0] && turn == 0)
                        ;
                    --value;//臨界區
                    flag[1] = false;
                }
            }
        }试一下!!!
      

  7.   

    互斥锁没有锁住临界区两端。互斥锁必须成对出现,一开一关,在你的程序里面互斥锁为turn。
    而且对于turn的操作不是原子操作,所以会出现调度失败的问题。
    使用循环实现PV有点忘了,如果还有需要,请邮箱[email protected]
      

  8.   

    你自己无法实现临界区。因为不能保证你所谓的临界区的代码执行是不可分割的。比如你的代码可能会按照这个顺序执行,虽然纪律非常非常小:
    flag[0] = true;flag[1] = true;turn = 1;
    while (flag[1] && turn==1)
    ;
    ++value;//臨界區turn = 0;
    while (flag[0] && turn == 0)
    ;
    --value;//臨界區而且你用了 busy loop 方式,这个方法在多线程中是不推荐使用的。