锁定一个对象

Eri*_*sch 5 c# locking

我经常看到这里显示的代码,即分配对象的位置,然后用作"锁定对象".

在我看来,你可以使用任何对象,包括事件本身作为锁对象.为什么要分配一个什么都不做的新对象?我的理解是在对象上调用lock()实际上不会改变对象本身,也不会实际锁定它被使用,它只是用作多个锁定语句锚定的占位符.

public class Shape : IDrawingObject, IShape
{
    // Create an event for each interface event
    event EventHandler PreDrawEvent;
    event EventHandler PostDrawEvent;

    object objectLock = new Object();

    // Explicit interface implementation required.
    // Associate IDrawingObject's event with
    // PreDrawEvent
    event EventHandler IDrawingObject.OnDraw
    {
        add
        {
            lock (objectLock)
            {
                PreDrawEvent += value;
            }
        }
        remove
        {
            lock (objectLock)
            {
                PreDrawEvent -= value;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,这真的是一件好事吗?

Mar*_*ell 7

包括事件本身

不,你做不到."事件"实际上只是一些存取方法.假设您的意思是支持委托,那将是非常糟糕的 - 委托是不可变的:每次添加/删除订阅者时,您都会获得不同的委托.

实际上,4.0编译器现在使用无锁代码执行此操作Interlocked- 可能值得遵循此方法.

在您的例子中,objectLock所有的来电者(该实例)被锁定对确保相同的对象,这是很重要的-但不锁定上的丑陋this(这是C#编译器如何使用工作).

-

更新:您的示例显示了在C#4.0之前必需的代码,访问类型的类似字段的事件直接与字段对话:不遵守正常的字段类事件锁定.这在C#4.0中有所改变; 你现在可以(在C#4.0中)安全地重写这个:

public class Shape : IDrawingObject, IShape
{
    // Create an event for each interface event
    event EventHandler PreDrawEvent;
    event EventHandler PostDrawEvent;

    event EventHandler IDrawingObject.OnDraw
    {
        add { PreDrawEvent += value; }
        remove { PreDrawEvent -= value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后遵循所有正确的行为.