【发布时间】:2015-06-17 05:09:57
【问题描述】:
我遇到了令我困惑的 lock 语句问题:
如果连接两个具有相同表达式("1" + "2") 的字符串,如下所示,lock 语句将该表达式实现为字符串并按预期锁定工作:
lock ("1" + "2")
{
Task.Factory.StartNew(() =>
{
lock ("1" + "2")
{//launched afetr 10 second
}
});
Thread.Sleep(10000);
}
但是如果在第一个lock ("1" + "2") 中更改为var a="1"; lock (a + "2")
虽然两个表达式具有相同的结果,但锁定语句将其作为两个不同的表达式处理,因此第二个锁定语句立即启动:
lock ("1" + "2")
{
Task.Factory.StartNew(() =>
{
var a = "1";
lock (a + "2")
{//launched immediately
}
});
Thread.Sleep(10000);
}
能否解释一下这种行为:
(我知道在 lock 语句中使用字符串 (MSDN) 违反了锁定准则。)
【问题讨论】:
-
奇怪的行为是因为字符串实习。有关锁定实习字符串的更多信息,请参阅this SO question
-
具有相同值的字符串不一定在相同的内存位置。编译器会自动将
"1" + "2"编译为"12",但a + "2"是在运行时创建的,即使它具有相同的值也会导致不同的字符串。因此,您锁定了一个不同的变量。 -
@ScottChamberlain - 我认为这与实习无关。您有参考来源的链接吗?
-
@ScottChamberlain 对,我直到现在才使用 String.Intern!请注意评论作为答案。
-
@Enigmativity:编译
"1" + "2"可以 与"12"是相同的字符串实例的唯一原因是字符串实习。 IE。编译器在编译时将所有相同的字符串文字静态实习为同一个对象。这可以也在运行时完成,但无论哪种方式实习都是行为背后的原因。