Man*_*ani 21 .net c# multithreading locking
根据我的理解,在运行时完成锁(obj)的代码块之前不会释放锁(因为当块完成时,它会调用Monitor.Exit(obj).
有了这种理解,我无法理解以下代码行为背后的原因:
private static string obj = "";
private static void RecurseSome(int number)
{
Console.WriteLine(number);
lock (obj)
{
RecurseSome(++number);
}
}
Run Code Online (Sandbox Code Playgroud)
// 电话: RecurseSome(0)
// 输出: 0 1 2 3...... stack overflow exception
必须有一些我缺少的概念.请帮忙.
小智 35
锁知道哪个线程锁定了它.如果同一个线程再次出现,它只会增加一个计数器而不会阻塞.
因此,在递归中,第二个调用也进入 - 并且锁在内部增加锁定计数器 - 因为它是相同的线程(已经持有锁).
MS-帮助://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_csref/html/656da1a4-707e-4ef6-9c6e-6d13b646af42.htm
或者MSDN:http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
状态:
lock关键字确保一个线程不进入代码的关键部分,而另一个线程处于临界区.如果另一个线程试图输入锁定的代码,它将等待,阻止,直到该对象被释放.
注意线程引用和强调"另一个"线程.
Ste*_*ven 35
请不要锁定字符串对象.这可能会导致意外行为,例如应用程序中的死锁.您当前正在锁定空字符串,这更糟糕.整个程序集使用相同的空字符串.并使事情变得更糟; 作为优化,CLR在AppDomains上重用字符串.锁定字符串意味着您可能正在进行跨域锁定.
使用以下代码作为锁定对象:
private readonly static object obj = new object();
Run Code Online (Sandbox Code Playgroud)
UPDATE
事实上,我认为允许锁定任何东西是安全的,这是.NET框架中的一个主要设计缺陷.相反,他们应该创建某种SyncRoot密封类,只允许该lock语句并Monitor.Enter接受实例SyncRoot.这会给我们带来很多苦难.我确实知道这个漏洞来自哪里; Java具有相同的设计.
正如其他人已经注意到的那样,锁是由线程进行的,因此可以正常工作.但是,我想在此添加一些内容.
微软的并发专家Joe Duffy有许多关于并发的设计规则.他的一个设计规则是:
9.避免在设计中锁定递归.尽可能使用非递归锁.
递归通常表示同步设计中的过度简化通常会导致代码不太可靠.一些设计使用锁递归作为一种方法来避免将函数拆分为带锁的函数和假设已经采用锁的函数.这无疑会导致代码大小的减少,从而缩短写入时间,但最终导致设计更加脆弱.
(来源)
要防止递归锁定,请将代码重写为以下内容:
private readonly static object obj = new object();
private static void Some(int number)
{
lock (obj)
{
RecurseSome(number);
}
}
private static void RecurseSome(int number)
{
Console.WriteLine(number);
RecurseSome(++number);
}
Run Code Online (Sandbox Code Playgroud)
此外,我的代码将抛出一个StackOverflowException,因为它永远不会以递归方式调用自身.您可以按如下方式重写您的方法:
private static void RecurseSome(int number)
{
Console.WriteLine(number);
if (number < 100)
{
RecurseSome(++number);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9836 次 |
| 最近记录: |