制作自定义对象线程安全的 [英] Making Custom Object Thread Safe

查看:148
本文介绍了制作自定义对象线程安全的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发布了一个更早问题有关返回集合,而线程安全的话题上来。我得到这个链接做一些更多的阅读,我发现这特别是行:

I posted an earlier question about returning collections, and the topic of thread safety came up. I was given this link to do some more reading, and I found this particular line:

在一般情况下,避免锁定在一个公开的类型,或超过
码的控件实例

In general, avoid locking on a public type, or instances beyond your code's control.

首先,纠正我,如果我错了,但不认为微软在公共型给锁,balance变量的例子吗?

First, correct me if I'm wrong, but doesn't the example that Microsoft give lock on a public type, the balance variable?

其次,我将如何去锁定我自己的getter / setter属性。假设我有以下类:

Secondly, how would I go about locking my own getter/setter property. Suppose I have the following class:

private int ID;

public Person(int id)
{
    this.Identification= id;

}

public int Identification
{
    get { return this.ID; }

    private set
    {
        if (value == 0)
        {
            throw new ArgumentNullException("Must Include ID#");
        }
        this.ID = value;
    }
}



getter方法是公共正确的?只有二​​传手声明私有。所以,我怎么会锁定,或者让我的getter / setter属性线程安全的?

The getter is public correct? Only the setter is declared private. So, how would I lock, or make my getter/setter properties thread safe?

推荐答案

当你需要锁定一个变量,你需要每一个地方使用了可变锁定到位左右。锁是不是一个变量 - 它是在使用一个变量的代码区域

When you need to lock on a variable, you need to lock around every place where the variable is used. A lock is not for a variable - it's for a region of code where a variable is used.

这不要紧,如果你在一个地方只读。 - 如果你需要锁定一个变量,你需要它的处处的在使用该变量。

It doesn't matter if you 'only read' in one place - if you need locking for a variable, you need it everywhere where that variable is used.

到替代是的 互锁 类 - 这使用处理器级别的原语锁定,这是一个快一点。 互锁,但不能保护多条语句(和具有2 互锁 stataments是不一样的内部具有这些2语句单锁定)。

An alternative to lock is the Interlocked class - this uses processor-level primitives for locking that's a bit faster. Interlocked, however cannot protect multiple statements (and having 2 Interlocked stataments is not the same as having those 2 statements inside a single lock).

当你锁定,您的必须的上的一个实例锁引用类型(其在大多数情况下(但不总是),也应是一个静态实例)。这是为了确保所有的锁实际上是取出来的的相同的实例,而不是它的一个副本。很显然,如果你使用在不同的地方的副本,你不锁同样的事情,所以你的代码不会被正确序列化

When you lock, you must lock on an instance of a reference type (which, in most cases (but not always), should also be a static instance). This is to ensure that all locks are actually taken out on the same instance, not a copy of it. Obviously, if you're using a copy in different places, you're not locking the same thing so your code won't be correctly serialized.

例如:

private static readonly object m_oLock = new object ();

...

lock ( m_oLock )
{
    ...
}

无论是安全使用非静态锁需要详细的代码分析 - 在某些情况下,它会导致更多的并行因为同一区域的码被锁定少,但它的分析可能是非常棘手的 - 如果你不确定,只需要使用静态锁定对象。 。服用一个打开的锁的成本是最小的,但不正确的分析可能会导致该拿年龄来调试错误

Whether it's safe to use a non-static lock requires detailed analysis of the code - in some situations, it leads to more parallelism because the same region of code is locked less but the analysis of it could be very tricky - if you're unsure, just use a static lock object. The cost of taking an open lock is minimal but incorrect analysis may lead to errors that take ages to debug.

编辑:

下面是显示如何锁定属性访问一个例子:

Here's an example showing how to lock property access:

private int ID; // do NOT lock on value type instances
private static readonly object Lock = new object ();

public Person(int id)
{
    this.Identification = id;
}

public int Identification
{
    get
    { 
        lock ( Lock )
        {
            return this.ID;
        }
    }

    private set
    {
        if (value == 0)
            throw new ArgumentNullException("Must Include ID#");

        lock ( Lock )
        {
            this.ID = value;
        }
    }
}



由于您的财产只有做了琐碎的get / set操作,您可以尝试使用的 Interlocked.CompareExchange ,而不是一个完整的锁 - 它会使事情变得稍微快一点。请记住,虽然,联锁操作是不一样的锁

Since your property only does a trivial get/set operation, you can try using Interlocked.CompareExchange instead of a full lock - it will make things slightly faster. Keep in mind, though, that an interlocked operation is not the same as a lock.

编辑2:

还有一件事:一个简单的get /上设置 INT 不需要锁 - 读取和写入一个32位的值(就其本身)已经是原子的。所以这个例子太简单了 - 只要你不尝试使用应该以原子方式完成多个操作 ID ,则不需要锁。但是,如果你真正的代码实际上是用 ID更加复杂被检查和设置,您可能需要锁定和的你需要锁定周围的一切,使操作了原子操作的。这意味着你可能要拉锁出的getter / setter - 2锁在get / set方法对的变量是不一样的他们身边一个锁

Just one more thing: a trivial get / set on an int doesn't need a lock - both reading and writing a 32-bit value (in and of itself) is already atomic. So this example is too simple - as long as you're not trying to use ID in multiple operations that should be completed in an atomic fashion, the lock is not needed. However, if your real code is actually more complicated with ID being checked and set, you may need locking and you'll need to lock around all the operations that make up the atomic operation. This means that you may have to pull the lock out of the getter / setter - 2 locks on a get/set pair of a variable is not the same as a single lock around them.

这篇关于制作自定义对象线程安全的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆