使用Environment.TickCount锁定C#

时间:2016-08-03 22:03:27

标签: c# locking

我移植了一些遗留代码并注意到某些类具有以下锁定对象:

protected readonly object _stateLock = Environment.TickCount;

对新对象()有什么好处吗? 我看到的另一个锁定对象是

private Nullable<int> _sLock = new Nullable<int>(Environment.TickCount);

使用它有什么好处吗?

1 个答案:

答案 0 :(得分:4)

不,没有任何优势。 Environment.TickCountNullable<int>值都是值类型,并且会被装箱,即包装在新的object引用中。

您的代码的第二个版本实际上更糟糕。第一个使用TickCount的方法只是分配新object引用的低效方法。但是引用永远不会改变,否则锁将正常工作。 lock语句(或者更确切地说,基础Monitor类)并不关心对象内部的值;它所关心的只是参考本身。所以装箱TickCount,或17或仅创建一个新object,它们都是一样的。

使用Nullable<int>的第二个版本是完全错误的,并且根本不会实现锁定行为。由于Nullable<int>本身就是一种值类型,因此当任何代码尝试锁定该值时,即lock (_sLock),该值将在该时间点装箱,从而创建全新的object引用只为那个锁。锁仅在需要共享数据的每个关键代码段也使用相同的object引用进行锁定时才起作用。由于它们都将获得自己的新object引用,因此根本不会发生同步。

我还应该指出编译器通常不允许你做第二个版本。即如果您尝试编译此代码,它将失败并显示错误:

Nullable<int> _sLock;

lock (_sLock) { }

错误将会读取

  

错误CS0185:&#39; int?&#39;不是lock语句

所要求的引用类型

如果你的代码实际上是按照你所说的那样编写的,那么编写代码的人可以通过转换_sLock值来绕过这个非常有用的编译器错误,例如类似的东西:

lock ((object)_sLock) { }

如果我看到这样的代码,我会立即质疑编写代码的人的能力,并且会坚持审查他们触及的任何应该是线程安全的代码,看看他们搞砸了什么起来。