【发布时间】:2016-07-22 06:58:11
【问题描述】:
为什么我们不能在 Lock C# 中使用值类型。我找到了一些原因,但看起来并不方便:
" 请记住,当您为 object 类型的参数传递值类型时,它会被装箱(包装)到引用类型中。这使得每次发生这种情况时它都是一个全新的对象。"
“您无法锁定值类型,因为它没有同步根记录。”
【问题讨论】:
标签: c# multithreading c#-4.0 task-parallel-library
为什么我们不能在 Lock C# 中使用值类型。我找到了一些原因,但看起来并不方便:
" 请记住,当您为 object 类型的参数传递值类型时,它会被装箱(包装)到引用类型中。这使得每次发生这种情况时它都是一个全新的对象。"
“您无法锁定值类型,因为它没有同步根记录。”
【问题讨论】:
标签: c# multithreading c#-4.0 task-parallel-library
原始值类型无处存储有关锁的所需信息。例如,int (Int32) 是 4 个字节的数据仅此而已。另一方面,object 具有相关联的几个头字节,锁定原语可以在需要时延迟存储(特定对象第一次被锁定时)。的确,所有值类型都可以处理作为对象(通过装箱),但这没有用,因为每次调用lock 都会单独装箱,所以你永远不会和同一个对象说话——它不会达到预期的结果。
顺便说一句,我个人认为允许您锁定任意对象是错误的。 Monitor 是一个 instance 类型似乎更加明显和直接,因此您只能锁定特定类型。那么这个问题就没有实际意义了。
【讨论】:
因为值类型的按值复制语义。
lock 使用 Monitor.Enter(yourValueTypeVariable) 超越引擎盖。
除了它们可能相等(按值)之外,两个线程的复制值之间没有任何关系,这对于同步目的来说是无用的信息。
考虑下面的例子:
static void Main(string[] args)
{
int x = 5;
int y = 4 + 1;
Task.Run(() => Method1(x));
Task.Run(() => Method2(y));
}
private static void Method1(int lockObject1)
{
lock (lockObject1)
{
}
}
private static void Method2(int lockObject2)
{
lock (lockObject2)
{
}
}
ValueTypes 的默认行为是 lockObject1 和 lockObject2 相等。但是您不希望这种行为对吗?
Monitor 类需要同步对象的引用,以确定尝试是否在同一个块上并使用同一个对象。
【讨论】: