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

  • 相关阅读:
    SQLMAP注入教程-11种常见SQLMAP使用方法详解
    VS2012/2013/2015/Visual Studio 2017 关闭单击文件进行预览的功能
    解决 IIS 反向代理ARR URLREWRITE 设置后,不能跨域跳转 return Redirect 问题
    Spring Data JPA one to one 共享主键关联
    JHipster 问题集中
    Spring Data JPA 定义超类
    Spring Data JPA查询关联数据
    maven命名
    maven仓库
    Jackson读取列表
  • 原文地址:https://www.cnblogs.com/y112102/p/3699869.html
Copyright © 2011-2022 走看看