我们遇到了一些性能问题,并正在考虑从一些经常使用的属性中删除一些线程安全锁。更确切地说,仅来自访问修饰符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;
}
}
}
}
答案 0 :(得分:2)
根据经验,切勿将优化置于线程安全之上。这被广泛认为是不良做法,并且是许多问题的直接结果。话虽这么说,不,它永远不会一半将值写入原子对象(例如int ActualValue
)中。如果您不在乎获得时的价值的完全准确性,那么您的方法实际上是好的。
编辑
总体而言,机器代码中的多步骤操作不是原子的。为了澄清我的答案,在Java中,bool
,char
,byte
,sbyte
,short
,ushort
,int
,uint
和float
类型都具有原子写入,因此不会被写入一半。但是,decimal
,double
,long
,ulong
和DateTime
类型没有原子写入,因此可以被部分书写。
答案 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();
}
}
}