博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 中的 lock的陷阱
阅读量:5108 次
发布时间:2019-06-13

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

旧事重提了,或许很多人会奇怪,为什么 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必须明确对象是不是想象中的同一实例。 
如果需要针对一个变化的值,从它的意义上的Equals方面进行 lock ,那怎么办? 
这个可以参考  http://www.lostinet.com/files/ 下的 HashCodeLock (里面很多细节可以优化) 

转载于:https://www.cnblogs.com/gc2013/p/3831919.html

你可能感兴趣的文章
ubuntu无法解析主机错误与解决的方法
查看>>
尚学堂Java面试题整理
查看>>
MySQL表的四种分区类型
查看>>
[BZOJ 3489] A simple rmq problem 【可持久化树套树】
查看>>
STM32单片机使用注意事项
查看>>
swing入门教程
查看>>
好莱坞十大导演排名及其代表作,你看过多少?
查看>>
Loj #139
查看>>
StringBuffer是字符串缓冲区
查看>>
hihocoder1187 Divisors
查看>>
Azure 托管镜像和非托管镜像对比
查看>>
js window.open 参数设置
查看>>
032. asp.netWeb用户控件之一初识用户控件并为其自定义属性
查看>>
Ubuntu下安装MySQL及简单操作
查看>>
前端监控
查看>>
clipboard.js使用方法
查看>>
移动开发平台-应用之星app制作教程
查看>>
leetcode 459. 重复的子字符串(Repeated Substring Pattern)
查看>>
伪类与超链接
查看>>
centos 7 redis-4.0.11 主从
查看>>