c#线程安全属性,不带锁的吸气剂怎么办?

时间:2018-08-15 10:49:57

标签: c# multithreading properties thread-safety

我们遇到了一些性能问题,并正在考虑从一些经常使用的属性中删除一些线程安全锁。更确切地说,仅来自访问修饰符getter。改进之处在于,如果其他一些线程在同一个属性上进行获取,则setter访问修饰符不再“被阻止”。

->当然,必须确保,例如,对于整数类型而言,位值为11110011(即243),一旦写入开始就写入所有位。必须确保写线程永远不会结束,并且get线程变成一半写位,从而导致错误的值。是这样吗?

如果是这样,那么该概念是否可用于所有内置数据类型的.net以及字符串?

请参见下面的代码示例,其中显示了这一概念:

    // for properties used just the "Built-In Types"
    // doc: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/built-in-types-table

    private int _ActualValue = 0;
    private readonly object _Lock_ActualValue = new object();
    public int ActualValue
    {
        get
        {
            //lock(_Lock_ActualValue)  <- remove lock for access modifier get ?
            //{
                return _ActualValue;
            //}
        }
        set
        {
            lock (_Lock_ActualValue)
            {
                if((value != _ActualValue) && (value < 1000))
                {
                    Log("_ActualValue", value.ToString());
                    _ActualValue = value;
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

根据经验,切勿将优化置于线程安全之上。这被广泛认为是不良做法,并且是许多问题的直接结果。话虽这么说,不,它永远不会一半将值写入原子对象(例如int ActualValue)中。如果您不在乎获得时的价值的完全准确性,那么您的方法实际上是好的。

编辑

总体而言,机器代码中的多步骤操作不是原子的。为了澄清我的答案,在Java中,boolcharbytesbyteshortushortintuintfloat类型都具有原子写入,因此不会被写入一半。但是,decimaldoublelongulongDateTime类型没有原子写入,因此可以被部分书写。

答案 1 :(得分:0)

private ReaderWriterLockSlim lockObj = new ReaderWriterLockSlim();

private int _ActualValue = 0;
public int ActualValue
{
    get
    {
        lockObj.EnterReadLock();

        try
        {
            return _ActualValue;
        }
        finally
        {
            lockObj.ExitReadLock();
        }
    }
    set
    {
        lockObj.EnterWriteLock();
        try
        {

            if((value != _ActualValue) && (value < 1000))
            {
                Log("_ActualValue", value.ToString());
                _ActualValue = value;
            }
        }
        finally
        {
            lockObj.ExitWriteLock();
        }
    }
}