none
为什么会出现下面的结果? RRS feed

  • 问题

  • public class CellProd
        {
            Cell cell; // 被操作的Cell对象      
            int quantity = 1; // 生产者生产次数,初始化为1       
            public CellProd(Cell box, int request)
            {        //构造函数        
                cell = box;
                quantity = request;
            }
            public void ThreadRun()
            {
                for (int looper = 1; looper <= quantity; looper++)
                    cell.WriteToCell(looper); //生产者向操作对象写入信息     
            }
        }
        public class CellCons
        {
            Cell cell;
            int quantity = 1;
            public CellCons(Cell box, int request)
            {                //构造函数        
                cell = box;
                quantity = request;
            }
            public void ThreadRun()
            {
                int valReturned;
                for (int looper = 1; looper <= quantity; looper++)
                    valReturned = cell.ReadFromCell();//消费者从操作对象中读取信息      
            }
        }
        public class Cell
        {
            int cellContents; // Cell对象里边的内容       
            bool readerFlag = false; // 状态标志,为true时可以读取,为false则正在写入       
            public int ReadFromCell()
            {
                lock (this) // Lock关键字保证了什么,请大家看前面对lock的介绍            
                {
                    //if (!readerFlag)//如果现在不可读取                
                    //{
                    //    try
                    //    {                        //等待WriteToCell方法中调用Monitor.Pulse()方法                       
                    //        Monitor.Wait(this);
                    //    }
                    //    catch (SynchronizationLockException e)
                    //    {
                    //        Console.WriteLine(e);
                    //    }
                    //    catch (ThreadInterruptedException e)
                    //    {
                    //        Console.WriteLine(e);
                    //    }
                    //}
                    Console.WriteLine("Consume: {0}", cellContents);
                    readerFlag = false;                //重置readerFlag标志,表示消费行为已经完成               
                    Monitor.Pulse(this);                 //通知WriteToCell()方法(该方法在另外一个线程中执行,等待中)           
                }
                return cellContents;
            }
            public void WriteToCell(int n)
            {
                lock (this)
                {
                    //if (readerFlag)
                    //{
                    //    try
                    //    {
                    //        Monitor.Wait(this); //  释放对象上的锁并阻止当前线程,直到它重新获取该锁,等待Pulse方法发出信号
                    //    }
                    //    catch (SynchronizationLockException e)
                    //    {
                    //        Console.WriteLine(e); //当同步方法(指Monitor类除Enter之外的方法)在非同步的代码区被调用       
                    //    }
                    //    catch (ThreadInterruptedException e)
                    //    {                            //当线程在等待状态的时候中止                        
                    //        Console.WriteLine(e);
                    //    }
                    //}
                    cellContents = n;
                    Console.WriteLine("Produce: {0}", cellContents);
                    readerFlag = true;
                    Monitor.Pulse(this);                 //向读线程发出信息,当前对象我已经解锁了,即状态改变了            
                }
            }
        }
        public class MonitorSample
        {
            public static void Main(String[] args)
            {
                int result = 0; //一个标志位,如果是0表示程序没有出错,如果是1表明有错误发生        
                Cell cell = new Cell();         //下面使用cell初始化CellProd和CellCons两个类,生产和消费次数均为20次        
                CellProd prod = new CellProd(cell, 10);
                CellCons cons = new CellCons(cell, 10);
                Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
                Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));        //生产者线程和消费者线程都已经被创建,但是没有开始执行         
                try
                {
                    producer.Start();
                    consumer.Start();
                    producer.Join();
                    consumer.Join();
                    Console.ReadLine();
                }
                catch (ThreadStateException e)
                {        //当线程因为所处状态的原因而不能执行被请求的操作        
                    Console.WriteLine(e);
                    result = 1;
                }
                catch (ThreadInterruptedException e)
                {        //当线程在等待状态的时候中止        
                    Console.WriteLine(e);
                    result = 1;
                }        //尽管Main()函数没有返回值,但下面这条语句可以向父进程返回执行结果      
                Environment.ExitCode = result;
            }
        }
    }
    怎么会出现下面的结果:
    Product:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Consume:1
    Product:2
    Product:3
    Product:4
    Product:5
    Product:6
    Product:7
    Product:8
    Product:9
    Product:10
    2010年1月17日 6:19

答案

  • 你好!
         由于你的程序是多线程的,所以每一次显示的结果都是不确定的!你多次执行程序的结果都是不一样的!
         因为线程的执行是系统负责调度的,我们无法具体控制他们的执行序列!
    周雪峰
    2010年1月17日 7:04
    版主
  • 这个是无法控制先后顺序的 如果你的程序需要用到先后顺序 那么就不适宜用多线程

     如果仅是某个方法需要用到多线程 你可以用Queue来保证先后顺序  但这个方法的执行仍然需要线程同步 即通过Moniter等来锁定,这样至少可以保证这个方法之前的其他方法可以同时运行
    Memory all alone in the moonlight~My Blog in .NET~~~
    2010年1月18日 8:58
    版主

全部回复

  • 你好!
         由于你的程序是多线程的,所以每一次显示的结果都是不确定的!你多次执行程序的结果都是不一样的!
         因为线程的执行是系统负责调度的,我们无法具体控制他们的执行序列!
    周雪峰
    2010年1月17日 7:04
    版主
  • 这个是无法控制先后顺序的 如果你的程序需要用到先后顺序 那么就不适宜用多线程

     如果仅是某个方法需要用到多线程 你可以用Queue来保证先后顺序  但这个方法的执行仍然需要线程同步 即通过Moniter等来锁定,这样至少可以保证这个方法之前的其他方法可以同时运行
    Memory all alone in the moonlight~My Blog in .NET~~~
    2010年1月18日 8:58
    版主