将对象锁定在属性中,c#

时间:2011-02-23 15:13:03

标签: c#

public ArrayList InputBuffer
{
    get { lock (this.in_buffer) { return this.in_buffer; } }
}

在调用InputBuffer.Clear?

时是否锁定了this.in_buffer

或者属性是否只是在获取对它的引用时锁定in_buffer对象;锁定退出,然后该引用用于清除?

4 个答案:

答案 0 :(得分:5)

不,该属性在获取引用时锁定引用。毫无意义,说实话......这种情况比较常见:

private readonly object mutex = new object();
private Foo foo = ...;

public Foo Foo
{
    get
    {
        lock(mutex)
        {
            return foo;
        }
    }
}

该锁只会 覆盖属性访问本身,并且不会对使用Foo执行的操作提供任何保护。但是,与完全没有锁相同,因为只要变量只是而持有相同的锁,它确保您在任何时候阅读Foo属性,您正在访问该属性的最新值...没有锁定,没有内存障碍,您可能会得到“陈旧”的结果。

这很弱,但值得了解。

就个人而言,我尝试使极少数类型的线程安全,并且那些往往有更合适的操作...但是如果你想编写做的修改和读取多个线程的属性的代码,这是这样做的一种方式。使用volatile也可以提供帮助,但它的语义非常微妙。

答案 1 :(得分:2)

对象被锁定在锁定调用的大括号内,然后它被解锁。

在这种情况下,锁定调用中唯一的代码是return this.in_buffer;

因此,在这种情况下,在调用InputBuffer.Clear期间,in_buffer未被锁定。

使用扩展方法解决您的问题的方法如下:

private readonly object _bufLock;
class EMClass{
    public static void LockedClear(this ArrayList a){
        lock(_bufLock){
            a.Clear();
        }
    }
}

现在你做的时候:

a.LockedClear();

Clear通话将在锁定中完成。

您必须确保仅在_bufLocks中访问缓冲区。

答案 2 :(得分:1)

除了其他人对锁的范围所说的内容之外,请记住你没有锁定对象,你只是基于对象实例锁定命名。

通常的做法是使用单独的锁互斥锁,如Jon Skeet所示。

如果在清除集合时必须保证同步执行,请公开一个清除集合的方法,让客户端调用它,并且不公开底层实现细节。 (无论如何,这都是好的做法 - 查看封装。)

答案 3 :(得分:1)

如前所述,这种锁定形式没有帮助。

public ArrayList InputBuffer
{
    get { lock (this.in_buffer) { return this.in_buffer; } }
}

因为它只将引用锁定到 ArrayList,而不是ArrayList本身。 lock(x) { }的设计可能有点误导。它不会以任何方式改变(锁定)x的状态。

您似乎需要的是:

private ArrayList _inBuffer;
private object _bufferLock;

public object GetItem(int x)
{
     lock (_bufferLock) { return _inBuffer[x]; }
}

public void SetItem(int x, object value)
{
     lock (_bufferLock) { _inBuffer[x] = value; }
}

围绕_inBuffer.Clear()等的类似方法