是锁定对布尔的访问权还是过度杀伤

| 我有一个主要设计为POCO类的类,其中各种线程和任务都可以读取其值,只有其他类偶尔会更新这些值。对于ReaderWriterLockSlim,这似乎是理想的方案。 问题是,在该类中,是否需要线程安全的属性,如果该属性是布尔型的,那是不是太过分了?如果是int会怎样?约会时间?
public class MyClass
{
  private bool _theValue = false;
  private ReaderWriterLockSlim _theValueLock = new ReaderWriterLockSlim();

  public bool TheValue
  {
    get
    {
      bool returnVal = false;
      try
      {
        _theValueLock.EnterReadLock();
        returnVal = _theValue;
      }
      finally
      { _theValueLock.ExitReadLock(); }
      return returnVal;
    }
    set
    {
      try
      {
        _theValueLock.EnterWriteLock();
        _theValue = value;
      }
      finally
      { _theValueLock.ExitWriteLock(); }
    }
  }
}
这是所有代码的过度杀伤力,并且简单...
public bool TheValue { get; set; }
...足够吗? 因为类型是布尔型,所以安全吗?如果是这样,什么时候变得不安全? 字节?诠释?约会时间? 编辑 我的基本体系结构是具有此类存储状态。也许有一个服务负责对此类进行写操作。所有其他类都可以基于此状态数据读取并执行其逻辑。我将尽力确保所有数据都是一致的,但是如下所述,我主要关心的是数据的原子性和碎片化。 结论 感谢每个人的回应,所有这些都很有价值。我主要关心的是写入/读取的原子性(即担心碎片)。对于.NET平台,如果所讨论的变量是小于4个字节的内置值类型,则读和写是原子的(例如,short和int很好,long和double则不是)。     
已邀请:
        您有几种选择。 没做什么。 使类不可变。 使用普通的旧
lock
。 将字段标记为“ 3”。 使用
Interlocked
方法。 由于对ѭ5的读写保证是原子的,因此您可能不需要执行任何操作。这在很大程度上取决于类使用方式的性质。原子性不等于线程安全。这只是它的一方面。 理想的解决方案是使您的类不可变。不可变类通常是线程安全的,因为它们不能被其他线程修改(或完全不能修改)。有时这只是不可行。 我在清单上的下一个偏好是普通的旧
lock
。获取和发布的开销非常小。实际上,我认为您会发现在大多数情况下
lock
会胜过
ReaderWriterLockSlim
,特别是如果您正在做的只是读/写变量。我自己的测试表明,RWLS的开销比2英镑慢5倍左右。因此,除非读操作异常长并且它们的数量大大超过写操作,否则RWLS将无济于事。 如果您担心锁开销,则务必将字段标记为“ 3”。请记住,ѭ3不是解决所有并发问题的灵丹妙药。不能替代
lock
。     
        根据使用方式的不同,您可能需要标记布尔值volatile。这将需要您的财产的备用字段。 您现在不需要像doing8那样处理它,因为它小于32位(假设您使用的是AutoLayout,有关详细信息,请参阅此文章,或者最详细的信息请参见本节)。在ECMA 335规范中名为“存储器访问的原子性”。如果您使用的类型大于此类型,则将需要某种形式的同步。 我建议:
public class MyClass
{
    private volatile bool _theValue = false;
    public bool TheValue 
    {
        get { return _theValue; } 
        set { _theValue = value; } 
    }
 }
    
        没有类型是真正安全的! 更准确地说,C#规范可确保您读取或分配小于4个字节或引用的结构类型是原子的。如果您的操作系统是64位,则对于小于8字节的结构,CLR可以通过确保相同的东西来做得更好。 但是,如果您不小心,除了赋值或读取值之外,任何更复杂的操作都可能被另一个竞争线程中断。 甚至像这样简单的事情:
myBool = !myBool
如果竞争线程修改myBool的值,可能会得到意外的结果。 如果您要确保不会发生类似的事情,建议使用锁。强烈建议不要使用volatile关键字,除非您确切地知道自己在做什么。检查这些博客文章以获取其他信息。 但是,在您的示例中,该属性仅执行一次写入或一次读取就没有其他作用,因此锁定是无用的。但是,如果有任何其他治疗,那就不会了。     

要回复问题请先登录注册