使用Monitor对资源进行保护(一)

简介: 首先,来看下使用system.threading.monitor对资源进行保护的思路:   即,使用排它锁,当线程A需要访问某一资源时,对其进行加锁,线程A获取到锁以后,任何其他线程如果再次对资源进行访问,则将其放到等待队列中,知道线程A释放锁之后,再将线程从队列中取出。



首先,来看下使用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);
        
        
        }
    
    }
}










目录
相关文章
|
3月前
|
微服务 Windows
【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式
【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式
|
3月前
|
数据采集 监控 Kubernetes
在k8S中,kubelet监控Worker节点资源是使用什么组件来实现的?
在k8S中,kubelet监控Worker节点资源是使用什么组件来实现的?
|
6月前
[已解决]该主机与 Cloudera Manager Server 失去联系的时间过长。 该主机未与 Host Monitor 建立联系。
[已解决]该主机与 Cloudera Manager Server 失去联系的时间过长。 该主机未与 Host Monitor 建立联系。
179 0
运行项目错误:资源繁忙或者锁定Error: EBUSY:resource busy or locked.lstat
运行项目错误:资源繁忙或者锁定Error: EBUSY:resource busy or locked.lstat
428 0
|
存储 Java 程序员
Monitor
我们Java程序员编码时谈论的最多的两个字就是对象,Java中几乎所有的技术都是围绕对象展开。本文将要讲述的Monitor并不是Java对象,而是在操作系统中关联的“对象”,Monitor是Java重量级锁synchronized实现的关键,因此学习Java单机同步机制就离不开对Monitor的剖析。Monitor从Java层面经常被人们称为监视器锁,而在操作系统层面称为管程。
557 2
Monitor
|
监控 安全 网络协议
[知识小节]Process Monitor介绍(上)
[知识小节]Process Monitor介绍
1198 0
[知识小节]Process Monitor介绍(上)
|
存储 监控 安全
[知识小节]Process Monitor介绍(下)
[知识小节]Process Monitor介绍
1089 0
[知识小节]Process Monitor介绍(下)
|
Prometheus 监控 Cloud Native
|
Oracle 关系型数据库 Linux
oom_kill_process造成数据库挂起并出现found dead shared server
这篇博客是上一篇博客Oracle shutdown immediate遭遇ORA-24324 ORA-24323 ORA-01089的延伸(数据库挂起hang时,才去重启的),其实这是我们海外一工厂的遇到的案例,把内容拆开是因为这个case分开讲述显得主题明确一些。
1303 0