zoukankan      html  css  js  c++  java
  • C#只能lock 引用类型的值 (转载)

    Lock:
            C#只能lock 引用类型的值,如果lock一个int, bool,编译器会报错。
        当一个互斥锁已被占用时,在同一线程中执行的代码仍可以获取和释放该锁。但是,在其他线程中执行的代码在该锁被释放前是无法获得它的。
        建议不要使用锁定对象类型之种方法来同步对静态数据的访问。您无权控制的其他代码可能也会锁定您的类类型。这可能导致死锁。因此,请使用锁定私有静态对象这种方法来同步对静态数据的访问。
        也就不是说不能写类似lock (typeof(this)) {} 的不规范语句。
    旧事重提了,或许很多人会奇怪,为什么 C# 不允许lock一个struct ? 例如:
    public void ProcessTask(int taskid){
        lock(taskid){  .....   }
    }
    编译说lock只能使用引用类型。有些人聪明(我想我以前也有这样的"聪明"。。),这样做: lock((object)taskid){...}
    但是,实际的经验告诉我,这样行不通,lock需要的是引用,严格来说是需要对象的实例。
    即使对象在意义上是相同的,但是如果不是ReferenceEquals的话,那么将作为两个实例来对待,那么C# lock 的就不是同一个东西。也就是说,当你以为这个 lock 生效的话,它其实在做无用工。
    在上面的例子,由于lock((object)taskid)每执行一次,taskid都进行一次装箱,而装箱后的对象不是同一个实例(都是完完全全的新的实例),所以 lock((object)taskid){...} 是白做了。
    当然,lock((object)123){} 这样的做法也是一样有问题的。
    但是这种就好点:lock(“helloworld“){} 。为什么只是“好点”,而不是“没有问题”了呢。原因在于DotNet分配字符串的机制。DotNet为每个Assembly里的字符串都分配固定的空间。所以每次引用“helloworld“的时候,是同一个实例。但是这个字符串不会在其他Assembly中得到共用。如果几个Assembly都是这样写的,那么它们各自有她们自己的“helloworld“
    比较好的做法:
    lock(this)...
    lock(typeof(ThisType))
    lock(GetType())//除非你明白这是干什么,否则不要乱来。
    lock(SomeType.StaticSyncObject)
    lock(someinst.SyncObject)
    其他的一些不好的做法
    lock(“task:“+id)
    lock(filename)
    当然,具体lock什么东西,是设计上的协议和规范。不过要注意的是,使用lock必须明确对象是不是想象中的同一实例。
    lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:
    Object thisLock = new Object();
    lock (thisLock)
    {
    // Critical code section
    }
    有关更多信息,请参见线程同步(C# 编程指南)。
    备注
    lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
    线程处理(C# 编程指南) 这节讨论了线程处理。
    lock 调用块开始位置的 Enter 和块结束位置的 Exit。
    通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
    如果实例可以被公共访问,将出现 lock (this) 问题。
    如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
    由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
    最佳做法是定义 private 对象来锁定, 或 private shared 对象变量来保护所有实例所共有的数据。

    原文链接

  • 相关阅读:
    php服务器安装memcache
    [PHP脚本]安装及使用
    [PHP]针对外服务器mail函数的php.ini配置
    [COBOL]安装配置及大型机模拟Hercules配置
    [Sqlite3].help中的命令介绍
    [NavigatLite4Mysql]DB管理工具使用
    [MS-SQLserver2005]Windows64位安装问题
    [MS-SQL]20130806_LocalDB_DOS命令使用
    [MS-SQL]20130806_LocalDB安装
    [MS]Microsoft SQL Server 2008 R2 开发版/企业版/标准版
  • 原文地址:https://www.cnblogs.com/OpenCoder/p/9989170.html
Copyright © 2011-2022 走看看