多线程同步_Monitor

多线程一直在学习和理解中......

Monitor类是多线程中用以实现同步的一种技术,主要是同一进程内多线程间的同步技术。
Monitor类中有以下几个方法需要注意:
Monitor.Enter(
object obj)方法,其意义相当于Lock(obj);
Monitor.Exit(
object obj)方法,意思是释放被锁的对象
Monitor.Wait(
object obj)方法,释放被锁的对象,并阻塞当前线程,等待其他线程通知(Pulse)再次获得锁 (个人理解 当前线程 锁 自己也阻塞了 要其他线程唤醒)

Monitor.Pulse(object obj)方法,通知等待加锁obj的线程解除阻塞,obj对象状态已经改变(个人理解 唤醒锁住线程 这样锁住线程继续执行 当前方法也继续执行)
 

注意的是:这两个方法是成对出现,通常使用在Enter,Exit之间。也可以用lock代替

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var td = new ThredDemo();

            Thread trOne = new Thread(new ParameterizedThreadStart(td.TrOne));
            Thread trTwo = new Thread(new ParameterizedThreadStart(td.TrTwo));

            //trOne启动线程
            trOne.Name = "trOne";
            trOne.Start(trOne.Name);

            //线程睡眠(相当于不参与cpu时间调度,通俗就是卡1000毫秒数)
            Thread.Sleep(1000);

            //trTwo启动线程
            trTwo.Name = "trTwo";
            trTwo.Start(trTwo.Name);

            Console.Read();
        }
    }

    class ThredDemo
    {
        public List<int> obj;
        int i = 0;

        public ThredDemo()
        {
            obj = new List<int>();
        }

        public void TrOne(object thredName)
        {
            //相当于lock 参考TrTwo
            Monitor.Enter(obj);

            Console.WriteLine("1");
            // TrOne释放对象上的锁并阻止当前线程这个时候TrTwo启动并进入临界区 
            Monitor.Wait(obj);

            Console.WriteLine("2");
            Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(),i);

            i++;
            Monitor.Pulse(obj);
            Console.WriteLine("3");

            //TrOne进入等待
            Monitor.Wait(obj);
            Monitor.Exit(obj);
            Console.WriteLine("4");
        }

        public void TrTwo(object thredName)
        {
            lock (obj)
            {
                //TrTwo通过Wait 释放进入 这个时候TrOne阻塞i的值++
                Console.WriteLine("5");
                i++;

                //释放等待的(Wait)的线程 并马上自己阻塞等待TrOne Pulse
                Monitor.Pulse(obj);

                Console.WriteLine("6");

                Monitor.Wait(obj);
                Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(), i);     
                
                //释放 这样console输出的4一定在7的后面 因为TrOne阻塞需要TrTwo释放 当前前提是程序无BUG
                Monitor.Pulse(obj); -----标记
                Console.WriteLine("7");
            }
        }
    }
}

为了方便理解自己加入输入查看效果 .

结果:

如果我把 TrTwo方法改下 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var td = new ThredDemo();

            Thread trOne = new Thread(new ParameterizedThreadStart(td.TrOne));
            Thread trTwo = new Thread(new ParameterizedThreadStart(td.TrTwo));

            //trOne启动线程
            trOne.Name = "trOne";
            trOne.Start(trOne.Name);

            //线程睡眠(相当于不参与cpu时间调度,通俗就是卡1000毫秒数)
            Thread.Sleep(1000);

            //trTwo启动线程
            trTwo.Name = "trTwo";
            trTwo.Start(trTwo.Name);

            Console.Read();
        }
    }

    class ThredDemo
    {
        public List<int> obj;
        int i = 0;

        public ThredDemo()
        {
            obj = new List<int>();
        }

        public void TrOne(object thredName)
        {
            //相当于lock 参考TrTwo
            Monitor.Enter(obj);

            Console.WriteLine("1");
            // TrOne释放对象上的锁并阻止当前线程这个时候TrTwo启动并进入临界区 
            Monitor.Wait(obj);

            Console.WriteLine("2");
            Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(),i);

            i++;
            Monitor.Pulse(obj);
            Console.WriteLine("3");

            //TrOne进入等待 1分钟后 注意的是
            // 如果指定的超时间隔已过,则线程进入就绪队列。
            Monitor.Wait(obj,60000);
            Monitor.Exit(obj);
            Console.WriteLine("4");
        }

        public void TrTwo(object thredName)
        {
            lock (obj)
            {
                //TrTwo通过Wait 释放进入 这个时候TrOne阻塞i的值++
                Console.WriteLine("5");
                i++;

                //释放等待的(Wait)的线程 并马上自己阻塞等待TrOne Pulse
                Monitor.Pulse(obj);

                Console.WriteLine("6");

                Monitor.Wait(obj);
                Console.WriteLine("线程{0}正在执行......i的值{1}", thredName.ToString(), i);

                //释放 这样console输出的4一定在7的后面 因为TrOne阻塞需要TrTwo释放 当前前提是程序无BUG

                // Monitor.Pulse(obj);
                Console.WriteLine("7");
            }
            Console.WriteLine("8");
        }
    }
}

把Monitor.Pulse(obj);注释掉了 TrOne方法 Monitor.Wait(obj,60000); 

运行后 4要等一分钟才输出 原因是 TrTwo方法没有释放 。

个人学习查看过程是 打印输出顺序查看执行过程 这样方便自己理解。

附加线程学习资料(来自博客园 )

逆时针の风  http://www.cnblogs.com/JimmyZheng/archive/2012/06/10/2543143.html

还有一线码农相对 逆时针の风 通俗懂一点

http://www.cnblogs.com/huangxincheng/category/362940.html

 以及  黑树 

http://www.cnblogs.com/maitian-lf/p/3678128.html

http://www.cnblogs.com/maitian-lf/p/3672390.html

原文地址:https://www.cnblogs.com/y112102/p/3699869.html