在 C# 中,类实例是引用类型。这是否意味着可以锁定 new 返回值的副本?就我而言,我有一个包含一些需要锁定的字段的类:
class Foo {
// ...
private Dictionary<IAsyncResult, string> fReadRequests;
private Dictionary<IAsyncResult, string> fWriteRequests;
private Dictionary<IAsyncResult, string> fSyncRequests;
}
在特定方法中,我需要对所有这些字段执行相同的操作。因此,为了避免代码重复,我通过将字段复制到数组中来循环执行操作:
var dictArray = new[] { fReadRequests, fWriteRequests, fSyncRequests };
foreach (var reqDict in dictArray) {
lock (reqDict) {
foreach (var i in reqDict) {
// Do something with the request.
}
}
}
这样安全吗?即使应用锁的变量是原始变量的副本,锁定也能按预期工作吗?
请您参考如下方法:
是的,您永远不会锁定保存引用的变量,您总是锁定实例。
在您的情况下,您复制的是引用,而不是对象,因此您在这些字段中处理的是相同的对象。
锁定那些应该工作得很好。
只知道:
- 锁定对象不会以任何方式阻止其他线程访问同一对象。如果其他线程没有锁定,它会跳华尔兹并更改对象,而不会理会您的锁定。
- 不要锁定您不拥有的对象,以及您发布给他人的对象。您需要确保您的代码是唯一锁定该对象的代码,否则如果其他一些代码也持有该对象的锁,您仔细的同步代码可能会突然停止。
- 永远不要锁定值类型,即使您将它们放在
object变量中也是如此。每次将值类型复制到object变量中时,您都会得到一个新副本,它将有自己的锁。
为了抵消 nbr。 2 你通常这样做:
private readonly object fLockReadQuests = new object();
然后锁定它。
但同样,您在问题中的假设成立。
