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

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

        }

    }
}
时间: 2024-12-28 06:43:17

使用Monitor对资源进行保护(一)的相关文章

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

使用Lock语句 首先来看一下出现的问题: 接着我们用Lock来解决这个问题: 创建线程安全类型 上面的类型Resource不是类型安全的,它的内部并没有采取线程安全(Thread-safe)的措施. 前面的线程同步时由类型的客户端program来实施的,之所以可行,完全是因为program的作者和resource的作者是同一个人. 因此,最好的办法是将获取锁,释放锁的逻辑放到resource内部来实现. 下面我们用两种方法来改进它: 方法一: 方法二: 使用Monitor来协调线程执行顺序 使

美团Android资源混淆保护实践

前言 Android应用中的APK安全性一直遭人诟病,市面上充斥着各种被破解或者汉化的应用,破解者可以非常简单的通过破解工具就能对一个APK进行反编译.破解.汉化等等,这样就可以修改原有代码的逻辑.添加新代码.添加或修改资源.或者更有甚者植入病毒等等,从而破坏原有APK的安全和用户体验,最终伤害到用户和原有的开发者. 而事物都是有两方面的,有矛就有盾,针对Android应用安全的各种方案应运而生,大家比较熟悉一般是各类加壳加固的工具,我们可以使用这些工具来保护我们的APK,加壳加固是另外一个话题

多线程同步与并发访问共享资源工具—Lock、Monitor、Mutex、Semaphore

"线程同步"的含义 当一个进程启动了多个线程时,如果需要控制这些线程的推进顺序(比如A线程必须等待B和C线程执行完毕之后才能继续执行),则称这些线程需要进行"线程同步(thread synchronization)". 线程同步的道理虽然简单,但却是给多线程开发带来复杂性的根源之一.当线程同步不好时,有可能会出现一种特殊的情形--死锁(Dead Lock). "死锁"的含义 死锁表示系统进入了一个僵化状态,所有线程都没有执行完毕,但却谁也没法继续

002-多线程-锁-同步锁-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现

一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. synchronized结论: 1.java5.0之前,协调线程间对共享对象的访问的机制只有synchronized和volatile,但是内置锁在功能上存在一些局限性,jdk5增加了Lock以及ReentrantLock. 2.java5.0,增加了一种新的机制:显式锁ReentrantLock,注意它

Linux下用信号量实现对共享内存的访问保护

转自:http://www.cppblog.com/zjl-1026-2001/archive/2010/03/03/108768.html 最近一直在研究多进程间通过共享内存来实现通信的事情,以便高效率地实现对同一数据的访问.本文中对共享内存的实现采用了系统V的机制,我们的重点在于通过信号量来完成对不同进程间共享内存资源的一致性访问,共享内存的具体方法请参见相关资料,这里不再赘述. 首先我们先实现最简单的共享内存,一个进程对其更新,另一个进程从中读出数据.同时,通过信号量的PV操作来达到对共享

cocos2dx游戏资源加密之XXTEA

在手机游戏当中,游戏的资源加密保护是一件很重要的事情. 我花了两天的时间整理了自己在游戏当中的资源加密问题,实现了跨平台的资源流加密,这个都是巨人的肩膀之上的. 大概的思路是这样的,游戏资源通过XXTEA加密方法对流的加密方式,有自己的密钥和标识,通过标识可知是否有加密,密钥是自己程序当中的.除非有密钥,否则很难通过解出正确的文件.经过加密后,加密文件也就是游戏资源放在resource的自己文件夹中,否则在xcode编译到趁机是会识别不了文件.在程序中cocos2dx底层加入解密过程,就可以把文

C++11线程指南(七)--资源竞争条件

1. 接口设计1 下面例子使用vector实现了一个栈.两个线程轮流从中弹出元素. #include <iostream> #include <thread> #include <mutex> #include <string> #include <vector> std::mutex myMutex; class Stack { public: Stack() {}; ~Stack() {}; void pop(); int top() { r

第四章——SQLServer2008-2012资源及性能监控(1)

原文:第四章--SQLServer2008-2012资源及性能监控(1) 性能优化的第一步是发现问题,而发现问题通常又有两类:突发问题的侦测和常规问题的侦测,对于常规问题的侦测,通常需要有一个长效的性能监控作为依据. 本系列文章介绍 服务器性能监控 CPU使用率监控 内存使用率监控 前言: 当由于劣质的查询写法.缺失必要的索引或者数据库级别的其他情况所导致的性能问题时,可以通过使用执行计划.DMVs/DMFs.SQL Trace或者数据库引擎顾问(DTA)这些手段来查找问题的根源. 但是,如果性

SpringCloud(9)使用Spring Cloud OAuth2保护微服务系统

一.简介 OAth2是一个标准的授权协议. 在认证与授权的过程中,主要包含以下3种角色. 服务提供方 Authorization Server. 资源持有者 Resource Server. 客户端 Client. OAuth2的认证流程如图所示,具体如下. (1)用户(资源持有者)打开客户端 ,客户端询问用户授权. (2)用户同意授权. (3)客户端向授权服务器申请授权. (4)授权服务器对客户端进行认证,也包括用户信息的认证,认证成功后授权给予令牌. (5)客户端获取令牌后,携带令牌向资源服