博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Monitor对资源进行保护(一)
阅读量:7091 次
发布时间:2019-06-28

本文共 4172 字,大约阅读时间需要 13 分钟。

首先,来看下使用system.threading.monitor对资源进行保护的思路:

 

即,使用排它锁,当线程A需要访问某一资源时,对其进行加锁,线程A获取到锁以后,任何其他线程如果再次对资源进行访问,则将其放到等待队列中,知道线程A释放锁之后,再将线程从队列中取出。

 

 主要的两个方法:

Enter

Exit

获取锁

释放锁

 

 

 接着是如何利用enter和exit方法实现线程保护的:

使用对象本身作为锁对象

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;//使用monitor解决和上面类似的问题,        //创建一个自定义的类型resource,然后在主线程和worker线程上调用他的record方法namespace Monitor{    public class Resource {        public string called;        //定义要访问的资源        public void Record() {            this.called += string.Format("{0}{1}",Thread .CurrentThread .Name ,DateTime .Now .Millisecond);            Console.WriteLine(called);        }    }    class Program    {        private Resource res = new Resource();        static void Main(string[] args)        {            Thread.CurrentThread.Name = "main ";            Program p = new Program();            Thread worker = new Thread(p.ThreadEntry );  //工作线程            worker.Name = "worker";            worker.Start();  //开启工作线程            p.ThreadEntry();  //主线程中调用同样的方法        }        //要同时共享的方法        void ThreadEntry() {                         System.Threading .Monitor.Enter(res);  //获取锁                res.Record();             System.Threading .Monitor.Exit(res);    //释放锁                    }    }}

使用System.Object作为锁对象

Monitor有一个限制,就是只能对引用类型加锁。
    如果将上面的Resource类型改为结构型,就会抛出异常
   解决的方法是将锁加载其他的引用类型上:
            比如system.object。此时,线程不会访问该引用类型的任何属性和方法,该对象的作用仅仅是协调各个线程。加锁思路:之前对于对象的加锁是占有A,操作A,释放A;现在的操作是占有B,操作A,释放B;

namespace 使用system.object作为锁对象{    //资源    public struct Resource {        public string Called;        public void Record() {            this.Called += string.Format("{0} {1}",Thread .CurrentThread .Name ,DateTime .Now .Millisecond);            Console.WriteLine(Called);                }    }    //    class Program    {        private Resource res = new Resource();//资源        private object lockobj = new object();  //用来加锁的介质        private object lockobj2 = new object();        static void Main(string[] args)        {            #region 只有一个加锁对象                //Thread.CurrentThread.Name = "main ";                //Program p = new Program();                //Thread worker = new Thread(p.ThreadEntry);  //创建新线程                //worker.Name = "worker";                //worker.Start();  //开启新线程                //p.ThreadEntry();             #endregion            #region 双对象:不能保证所有线程加锁和释放锁都是针对同一个对象B            Thread.CurrentThread.Name = "main ";            Program p = new Program();            ParameterizedThreadStart ts = new ParameterizedThreadStart(p.ThreadEntry);            Thread worker = new Thread(p.ThreadEntry);  //创建新线程            worker.Name = "worker";            //注意下面工作线程和主线程不是针对一个对象进行加锁的。。。运行时会得出他俩一起进入的时间            worker.Start(p.lockobj);  //开启新线程            p.ThreadEntry(p.lockobj2);             #endregion        }        void ThreadEntry(object obj) {            Monitor.Enter(obj);            res.Record();            Monitor.Exit(obj);        }        #region 一个对象加锁            //void ThreadEntry()            //{            //    Monitor.Enter(lockobj);//获取锁            //    res.Record();            //    Monitor.Exit(lockobj);//释放锁            //}         #endregion    }}

使用System.Type作为锁对象

    为了改进使用System.Object作为锁对象时,需要单独创建一个对象加锁使用,不够简洁,所以使用Sytem.type作为锁对象。

   使用type的好处是:多次调用typeof(type)获取的是同一个对象

namespace 使用system.type作为锁对象{    class Program    {        static void Main(string[] args)        {            Thread.CurrentThread.Name = "main ";            Program p = new Program();            Thread worker = new Thread(p.ThreadEntry);  //创建新工作线程            worker.Name = "worker";            worker.Start();  //开启工作线程            p.ThreadEntry(); //main里面开启工作线程        }        void ThreadEntry() {            Monitor.Enter(typeof(Resource));//获取锁            Resource.Record();            Monitor.Exit(typeof (Resource));  //释放锁                }    }    public static class Resource{                public static string Called;        public static void Record(){                    Called += String.Format("{0} {1}",Thread .CurrentThread .Name ,DateTime .Now .Millisecond);            Console.WriteLine(Called);                        }        }}

转载地址:http://ofsql.baihongyu.com/

你可能感兴趣的文章
HTTP Header 详解
查看>>
EasyUI效果--DataGrid的编辑效果
查看>>
IntelliJ IDEA---java的编译工具【转】
查看>>
Gradle用户指南(2)-基本命令
查看>>
python requests的安装与简单运用
查看>>
图像处理之opencv---常用函数
查看>>
给iPhone X都不换?这台白色版魅族机太耐看了!
查看>>
女生烫染七小时太漫长怎么解闷呢?
查看>>
天猫超级品牌日:新零售营销应该这么玩
查看>>
阿里巴巴PouchContainer发布0.2.1版本,剑指企业级
查看>>
最强科技实力支撑海尔走出“全球化”道路
查看>>
郭忆:网易数据库高可用架构最新进展!
查看>>
四川眉山中院宣判两起特大跨国电信诈骗案
查看>>
故宫珍宝馆完成二期改陈 珍贵红珊瑚盆景揭开面纱
查看>>
“平潭-高雄”货运直航顺利首航
查看>>
2018年澳门赌场毛收入增14% 贵宾厅增长放缓
查看>>
杭州机场春运预计起降航班3.3万架次 国际和地区增开428架次
查看>>
菲律宾一座“慰安妇”少女像设置仅两天就被撤走
查看>>
美总统特朗普驳斥美媒涉通俄门报道:极具侮辱性
查看>>
[2]十道算法题【Java实现】
查看>>