• C# 使用lock关键字lock不同的对象


    c# lock关键字的本质

    是调用Monitor.Enter(object obj)并且在finally的时候调用Monitor.Exit(obj)

     

    在obj是不同数据类型的时候会出现不同的情况

    1.锁定类型 例如lock(typeof(int))  lock(typeof(ClassA))   // CalssA 是一个类的定义

      备注:前者作用范围跨AppDomain 不跨Process, 后者不跨AppDomain(默认设置)

      使用范围:绝不推荐使用

    2.锁定字符串 例如lock("abc") 和lock(s)//s是一个字符串的实例变量

      备注:当字符串已经驻留在内存的时候 这个lock是有效的, 如果字符串未驻留在内存那么这个lock就失效了,该lock是跨Appdomain不跨Process

      使用范围: 一般不推荐使用

      以下代码显示了非驻留字符串导致的无法lock的问题,请在实际应用中避免lock(a+b)即使他们的值一样 (vs2008 Debug)

     

     

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
    class Program
    {
    staticvoid Main(string[] args)
    {
    string s1 ="a";
    string s2 ="bc";

    ThreadPool.QueueUserWorkItem(p
    =>
    {
    Thread.Sleep(
    3000); Console.WriteLine(" Thread2 Begin Test");
    lock (s1 + s2)
    {
    Console.WriteLine(
    "Thread2 Begin Lock");
    Thread.Sleep(
    1000);
    Console.WriteLine(
    "Thread2 End Lock");
    }
    });
    Console.WriteLine(
    "Thread1 Begin Test");
    lock (s1 + s2)
    {
    Console.WriteLine(
    "Thread1 Begin Lock");
    Thread.Sleep(
    10000);
    Console.WriteLine(
    "Thread1 End Lock");
    }
    }
    }
    }

    3.所有继承于System.MarshalByRefObject 的对象  ,例如Remoting Service之类的

      备注:锁定的是代理对象,在远端的对象并没有被锁定(byValue 和byRef 两种类型传数据也有影响)

      使用范围:不推荐

    4.值类型, 由于众所周知的装箱的问题...实际上锁定根本不生效

      使用范围:不推荐

    5. 应用[MethodImpl(MethodImplOptions.Synchronized)]标记的类

      实例方法锁定的是this   lock(this)

      静态方法锁定的是typeof(ClassName)   lock(typeof(ClassName)) //ClassName是你当前的类名

      使用范围:不推荐, 调用静态方法将导致锁定类型, 实例方法之间也相互影响锁定关系

    6.lock(this)

      很容易误用,例如在web page上调用 lock(this)....由于asp.net会为每次httpRequest , new一个类的实例...所以lock(this)在这里一点作用都没有

      在其他的情况下:lock(this)锁定了本身,那么但其他外部对象试图使用这个类的时候会有困扰

      如果你的类是public给其他人用的,那么最好不要lock(this)

      请参考以下代码(不推荐使用)

      

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
    publicclass ClassA
    {
    publicvoid Test()
    {
    lock (this)
    {
    Console.WriteLine(
    "Test Begin Lock");
    Thread.Sleep(
    10000);
    Console.WriteLine(
    "Test End Lock");
    }
    }
    }
    class Program
    {
    staticvoid Main(string[] args)
    {
    ClassA classA
    =new ClassA();

    ThreadPool.QueueUserWorkItem(p
    =>
    {
    Thread.Sleep(
    3000); Console.WriteLine(" Thread2 Begin Test");
    lock (classA)
    {
    Console.WriteLine(
    "Thread2 Begin Lock");
    Thread.Sleep(
    1000);
    Console.WriteLine(
    "Thread2 End Lock");
    }
    });
    classA.Test();
    Console.ReadLine();
    }
    }
    }

    7. lock(null) 必然抛出一个异常

    8.推荐使用以下方法lock

      private static object asyncLock=new object();

      lock(asyncLock)

      使用 private object asyncLock=new object(); 也是ok的,但是请注意避免之前提到的WebPage每次new一个类导致lock失效的问题

      影响范围不跨AppDomain

      PS1:关于跨不跨AppDomain的问题,其实用处不大,大部分应用程序都只是创建一个DefaultDomain

      PS2:可以将一些Assembly设置为跨AppDomain的,以减少内存浪费和提高性能, 例如string和一些基本类型都是这样实现的

      PS3:本人水平有限,如果错漏还请大家帮忙...

  • 相关阅读:
    根据字典中值得大小,对字典中的项排序
    统计序列中元素出现的频度
    为元组中的每个元素命名,提高程序可读性
    CentOS7 zabbix服务 简单安装文档
    使用脚本打印杨辉三角
    python 内置函数
    图片爬取实战一
    logstash的各个场景应用(配置文件均已实践过)
    kettle添加hadoop cluster时报错Caused by: java.lang.IllegalArgumentException: Does not contain a valid host:port authority: hadoop:password@node56:9000
    Jenkins+maven+Tomcat+SVN一键自动打包部署应用到服务器
  • 原文地址:https://www.cnblogs.com/qixuejia/p/4936198.html
Copyright © 2020-2023  润新知