zoukankan      html  css  js  c++  java
  • 多线程同步_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

  • 相关阅读:
    格子地图生成导航网格
    Geometry Shader 实现 Wireframe 绘制边线的Shader
    体素爆炸
    弹孔,血迹 等受击表现
    Behaviac 腾讯开源行为树 简介(给策划)
    unable to unroll loop 报错
    Unity编辑器扩展
    追踪弹路径
    代码管理资源属性
    主机排行网重大更新,移动端自适应
  • 原文地址:https://www.cnblogs.com/y112102/p/3699869.html
Copyright © 2011-2022 走看看