1

我有一个具有两个属性和两个方法的类。比如下面这个。(请忽略数据类型或返回类型,这只是一个典型场景)

// The methods could be invoked by multiple threads
    public class Stock
    { 

    private static int FaceValue {get; set;}
    private static int Percent (get; set;}

    //    method that updates the two properties
    Public void UpdateStock()
    {
      FaceValue += 1;
      Percent = FaceValue * 100;
    }

    //   method that reads the two properties
    public int[] GetStockQuote()
    {
        return new int[] { FaceValue, Percent};
    }

    }

我需要确保这个类是线程安全的。我可以在这两种方法中使用 lock(obj) 作为一种使其成为线程安全的技术,但考虑到以下几点,使它成为线程安全的最佳技术是什么:

  1. 只有两个属性被读取/更新。因此,不确定锁定在方法内部是否是一种好技术。

  2. 如果我只是让属性线程安全而不是方法或类就足够了吗?

  3. 另外,有没有办法使整个类线程安全而不是单个方法或属性?.Net 4.0 中的任何推荐锁定技术?

只是想知道我是否正在考虑这项权利,或者考虑到这些,我是否过于复杂了。非常感谢提前帮助我弄清楚这一点。

玛尼

4

2 回答 2

6

一般来说, alock可能是这里最简单的方法。

一个可能更好的选择是使这个类不可变。如果你这样做了,一旦创建了类就不能更改类中的值,那么在读取值时就不必担心了,因为它们无法被修改。

在这种情况下,可以通过使用一个接受两个值的构造函数来完成,并将其更改UpdateStock为更像:

public Stock GetUpdatedStock()
{
     // Create a new instance here...
     return new Stock(this.FaceValue + DateTime.Now.MilliSecond, this.FaceValue * 100);
}

编辑:

现在您已将 FaceValue 和 Percent 设为静态,您将需要同步。Alock可能是这里最简单的选项。

使用单个 value,您可能会使用Interlocked 类以原子方式处理更新,但无法对两个值进行原子更新*,这可能是正确完成线程安全所必需的。在这种情况下,通过 a 同步lock将解决您的问题。

*注意:如果您将两个值都放在一个类中并交换整个类实例,则可以在没有锁的情况下完成此操作 - 但这可能Interlocked.CompareExchange比它的价值要麻烦得多。

于 2012-10-08T15:51:52.463 回答
1

没有使线程安全的灵丹妙药解决方案,每个场景都需要自己的解决方案。最明显的是使用 a lock,但在您的示例中,您可以简化和使用Interlocked该类,并让它成为原子操作:

public class Stock
{ 

    private static int FaceValue {get; set;}

    Public void UpdateStock()
    {
       //only a single property to update now
       Interlocked.Increment(FaceValue);
    }

    //   method that reads the two properties
    public int[] GetStockQuote()
    {
        var currVal = FaceValue;
        return new int[] { currVal, currVal * 100 };
    }

}

请参阅MSDN 上的互锁

于 2012-10-08T16:17:14.653 回答