何时在C#中使用Monitor类或lock关键字来确保线程安全?
编辑:
到目前为止,答案似乎lock是对Monitor课程的一系列调用的简写.锁定电话到底是什么?或者更明确地说,
class LockVsMonitor
{
private readonly object LockObject = new object();
public void DoThreadSafeSomethingWithLock(Action action)
{
lock (LockObject)
{
action.Invoke();
}
}
public void DoThreadSafeSomethingWithMonitor(Action action)
{
// What goes here ?
}
}
Run Code Online (Sandbox Code Playgroud)
更新
谢谢大家的帮助:我发布了另一个问题,作为您提供的一些信息的后续跟进.由于您似乎精通这一领域,我发布了链接:此锁定和管理锁定异常的解决方案有什么问题?
遵循这个问题 - 使用C#传递方法作为参数和我的一些个人经验我想更多地了解调用委托与仅在C#中调用方法的性能.
虽然代表非常方便,但我有一个应用程序通过委托做了很多回调,当我们重写这个使用回调接口时,我们得到了一个数量级的速度提升.这是使用.NET 2.0所以我不确定3和4的情况如何变化.
如何在编译器/ CLR内部处理对委托的调用,这对方法调用的性能有何影响?
编辑 - 澄清代表与回调接口的含义.
对于异步调用,我的类可以提供一个OnComplete事件和调用者可以订阅的相关委托.
或者,我可以使用调用者实现的OnComplete方法创建一个ICallback接口,然后将其自身注册到类,然后在完成时调用该方法(即Java处理这些事情的方式).
为什么锁定非静态字段被认为是不好的做法?
并且,如果我没有锁定非静态字段,那么如何锁定实例方法而不将该方法锁定在相同或派生类的所有其他实例上?
我写了一个例子来使我的问题更清楚.
public abstract class BaseClass
{
private readonly object NonStaticLockObject = new object();
private static readonly object StaticLockObject = new object();
protected void DoThreadSafeAction<T>(Action<T> action)
where T: BaseClass
{
var derived = this as T;
if(derived == null)
{
throw new Exception();
}
lock(NonStaticLockObject)
{
action(derived);
}
}
}
public class DerivedClass :BaseClass
{
private readonly Queue<object> _queue;
public void Enqueue(object obj)
{
DoThreadSafeAction<DerivedClass>(x=>x._queue.Enqueue(obj));
}
}
Run Code Online (Sandbox Code Playgroud)
如果我对它进行了锁定StaticLockObject,那么该DoThreadSafeAction方法将被锁定所有派生的类的实例,BaseClass这不是我想要的.我想确保在锁定对象的特定实例时没有其他线程可以调用方法.
更新
谢谢大家的帮助:我发布了另一个问题,作为您提供的一些信息的后续跟进.由于您似乎精通这一领域,我发布了链接:此锁定和管理锁定异常的解决方案有什么问题?