天天看点

C#多线程学习笔记(四) --Lock and Monitor之二

a.Monitor方法(MSDN摘录)

获取对象锁,此操作同样会标记临界区的开头。其他任务线程都不能进入临界区,除非它使用其他锁定对象执行临界区的指令。

Wait

释放对象上的锁以便允许其他线程锁定和访问该对象。在其他线程访问对象时,调用线程将等待。脉冲信号用于通知待待线程有关对象状态的更改。

Pulse(信号),PulseAll

向一个或多个等待线程发送信号。该信号通知等待线程锁定对象的状态已更改,并且锁的所有者准备释放该锁。等待线程被放置在对象的就绪队列中以便它可以最后接收对象锁。一旦线程摇篮有了锁,它就可以检查对象的新状态以查看是否达到所需状态。

Exit

释放对象上的锁。此操作还标记受锁定对象保护的临界区的结尾。

b.Sample

C#多线程学习笔记(四) --Lock and Monitor之二

using System;

C#多线程学习笔记(四) --Lock and Monitor之二

using System.Collections.Generic;

C#多线程学习笔记(四) --Lock and Monitor之二

using System.Text;

C#多线程学习笔记(四) --Lock and Monitor之二

using System.Threading;

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

namespace ThreadLockAndMonitor

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

{

C#多线程学习笔记(四) --Lock and Monitor之二

    public class Cell

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        int cellContents;// Cell对象里边的内容

C#多线程学习笔记(四) --Lock and Monitor之二

        bool FAllowReader = false;// 状态标志,为true时可以读取,为false则正在写入

C#多线程学习笔记(四) --Lock and Monitor之二

        public int ReadfromCell()

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            lock (this)// Lock关键字保证了该块只有一个线程可以进来

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                if (!FAllowReader)//如果现在不可读取

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                    try

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                        //等待WriteToCell方法中调用Monitor.Pulse()方法

C#多线程学习笔记(四) --Lock and Monitor之二

                        Monitor.Wait(this);

C#多线程学习笔记(四) --Lock and Monitor之二

                    }

C#多线程学习笔记(四) --Lock and Monitor之二

                    catch (SynchronizationLockException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                        Console.WriteLine(e.Message);

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                    catch (ThreadInterruptedException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                        Console.WriteLine(e);

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                }

C#多线程学习笔记(四) --Lock and Monitor之二

                Console.WriteLine("Consume:{0}", cellContents);

C#多线程学习笔记(四) --Lock and Monitor之二

                FAllowReader = false;//重置FAllowReader标志,表示消费行为已经完成

C#多线程学习笔记(四) --Lock and Monitor之二

                Monitor.Pulse(this);//通知WriteToCell()方法(该方法在另外一个线程中执行,等待中)

C#多线程学习笔记(四) --Lock and Monitor之二

            }

C#多线程学习笔记(四) --Lock and Monitor之二

            return cellContents;

C#多线程学习笔记(四) --Lock and Monitor之二

        }

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        public void WriteToCell(int _n)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            lock(this)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                if (FAllowReader)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                    catch(SynchronizationLockException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                        //当同步方法(指Monitor类除Enter之外的方法)在非同步的代码区被调用

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                    catch(ThreadInterruptedException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                        //当线程在等待状态的时候中止

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                cellContents = _n;

C#多线程学习笔记(四) --Lock and Monitor之二

                Console.WriteLine("Procduce:{0}", cellContents);

C#多线程学习笔记(四) --Lock and Monitor之二

                FAllowReader = true;

C#多线程学习笔记(四) --Lock and Monitor之二

                Monitor.Pulse(this);//通知另外一个线程中正在等待的ReadFromCell()方法

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

  }

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

    public class CellProd

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        Cell cell;// 被操作的Cell对象

C#多线程学习笔记(四) --Lock and Monitor之二

        int quantity = 1;//生产者生产次数,初始化为1

C#多线程学习笔记(四) --Lock and Monitor之二

        public CellProd(Cell _box, int _request)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            cell = _box;

C#多线程学习笔记(四) --Lock and Monitor之二

            quantity = _request;

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        public void ThreadRun()

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            for(int i = 1; i<=quantity; i++)

C#多线程学习笔记(四) --Lock and Monitor之二

                cell.WriteToCell(i);//生产者向操作对象写入信息

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

    }

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

    public class CellCons

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        Cell cell;

C#多线程学习笔记(四) --Lock and Monitor之二

        int quantity = 1;

C#多线程学习笔记(四) --Lock and Monitor之二

        public CellCons(Cell _box, int _request)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            int valReturned;

C#多线程学习笔记(四) --Lock and Monitor之二

            for (int i = 1; i<=quantity; i++)

C#多线程学习笔记(四) --Lock and Monitor之二

                valReturned = cell.ReadfromCell();//消费者从操作对象中读取信息

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

    class Program

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

        static void Main(string[] args)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            int result = 0;//一个标志位,如果是0表示程序没有出错,如果是1表明有错误发生

C#多线程学习笔记(四) --Lock and Monitor之二

            Cell cell = new Cell();

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            //下面使用cell初始化CellProd和CellCons两个类,生产和消费次数均为20次

C#多线程学习笔记(四) --Lock and Monitor之二

            CellProd prod = new CellProd(cell, 20);

C#多线程学习笔记(四) --Lock and Monitor之二

            CellCons cons = new CellCons(cell, 20);

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            Thread producer = new Thread(new ThreadStart(prod.ThreadRun));

C#多线程学习笔记(四) --Lock and Monitor之二

            Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            //生产者线程和消费者线程都已经被创建,但是没有开始执行

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            try

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                producer.Start();

C#多线程学习笔记(四) --Lock and Monitor之二

                consumer.Start();

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                producer.Join();

C#多线程学习笔记(四) --Lock and Monitor之二

                consumer.Join();

C#多线程学习笔记(四) --Lock and Monitor之二

                Console.ReadLine();

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            catch(ThreadStateException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                Console.WriteLine(e);

C#多线程学习笔记(四) --Lock and Monitor之二

                result = 1;

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            catch(ThreadInterruptedException e)

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

                //当线程在等待状态的时候中止

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

            //尽管Main()函数没有返回值,但下面这条语句可以向父进程返回执行结果

C#多线程学习笔记(四) --Lock and Monitor之二

            Environment.ExitCode = result;

C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二
C#多线程学习笔记(四) --Lock and Monitor之二

}

C#多线程学习笔记(四) --Lock and Monitor之二

 可以看到,在上面的例程中,同步是通过等待Monitor.Pulse()来完成的。首先生产者生产了一个值,而同一时刻消费者处于等待状态,直到收到生产者的“脉冲(Pulse)”通知它生产已经完成,此后消费者进入消费状态,而生产者开始等待消费者完成操作后将调用Monitor.Pulese()发出的“脉冲”。它的执行结果很简单:

Produce: 1

Consume: 1

Produce: 2

Consume: 2

Produce: 3

Consume: 3

...

Produce: 20

Consume: 20

事实上,这个简单的例子已经帮助我们解决了多线程应用程序中可能出现的大问题,只要领悟了解决线程间冲突的基本方法,很容易把它应用到比较复杂的程序中去。