我有一个简单的课,例如:

  public class XXX
  {
    double val1;
    double val2;
    double delta;
    public void SetValues(double v1, double v2)
    {
      val1 = v1;
      val2 = v2;
      delta = val1 - val2;
    }

    public double Val1 { get { return val1; } }
    public double Val2 { get { return val2; } }
    public double Delta { get { return delta; } }
  }

, ,一个用于设置值的线程和读取值的多个线程。所以一个人可以使用 lock() 使所有阅读和写入不间断。但 我知道 同步从未实现,总有机会 Val1 - Val2 可能不等于 Delta 我不在乎. 。我的关注是更多地是通过Getters获得稳定的值。然而 lock() 对于这种情况很昂贵,因为大多数读者会工作。

我想到的下一个最好的事情就是使用 Interlocked.Exchange()

    public void SetValues(double v1, double v2)
    {
      Interlocked.Exchange(ref val1, v1);
      Interlocked.Exchange(ref val2, v2);
      Interlocked.Exchange(ref delta, v1 - v2);
    }

    public double Val1 { 
      get 
      {
        double val = 0;
        Interlocked.Exchange(ref val, val1);
        return val; 
      } 
    }

但是代码对我来说似乎很愚蠢。我不知道。

也是如此 lock() 说得通?我应该使用 Interlocked.Exchange() 出于绩效增长?还是我还能做什么?

有帮助吗?

解决方案

对于多个读者 /作家的场景,我将使用 ReaderWriterlockslim.

Represents a lock that is used to manage access to a resource, 
allowing multiple threads for reading or exclusive access for writing.

Use ReaderWriterLockSlim to protect a resource that is read by multiple 
threads and written to by one thread at a time. ReaderWriterLockSlim 
allows multiple threads to be in read mode, allows one thread to be in 
write mode with exclusive ownership of the lock, and allows one thread 
that has read access to be in upgradeable read mode, from which the 
thread can upgrade to write mode without having to relinquish its 
read access to the resource.

其他提示

您需要锁定整个setValues方法:

private object lockObject = new object();

public void SetValues(double v1, double v2)
{
  lock(lockObject)
  {
    val1 = v1;
    val2 = v2;
    delta = val1 - val2;
  }
}

public double Val1 { get { lock(lockObject) { return val1; } } }
public double Val2 { get { lock(lockObject) { return val2; } } }
public double Delta { get { lock(lockObject) { return delta; } } }

读者仍然可以获得不属于的val1,val2和delta,因为他们以几个步骤阅读了它。

您可以将val1,val2和delta放入一个值对象,该对象一次被检索一次,并且不会更改:

public Values Val1
{ 
  get 
  { 
    lock(lockObject) 
    { 
      // create a consistent object which holds a copy of the values
      return new Values(val1, val2, delta); 
    } 
  }
}

struct Values
{
  // ...
  public double Val1 { get /* ... */ }
  public double Val2 { get /* ... */ }
  public double Delta  { get /* ... */ }
}

如果您需要Getters返回稳定的结果,并且只需要维护内部同步,则建议您创建一个名为“快照”的类(包含Val1,Val2和Delta)或类似的类似。在您的设定器中,构建此类的新副本并将其交换为实例变量。在您的Getter中,只需返回快照的当前副本即可。只要呼叫者需要一致的体验,他们就会使用单个getter调用返回的单个快照实例。

因此,您必须放弃多个Getter-没有办法(没有外部同步)来确保Val1,Val2和Delta在否则中是一致的。


public class XXX
  {
    public class Snapshot {
      double val1;
      double val2;
      double delta;
      public Snapshot (double val1,double val2)
      {
         this.val1 = val1;
         this.val2 = val2;
         this.delta = val1 - val2;
      }
      public double Val1 { get { return val1; } }
      public double Val2 { get { return val2; } }
      public double Delta { get { return delta; } }
    }
    Snapshot _current;
    public void SetValues(double v1, double v2)
    {
      Snapshot s = new Snapshot(v1,v2);
      /* If there were subsequent steps needed to get the snapshot "ready", you could do them here.
         Otherwise, I think you can do this as a single assignment into _current above */
      _current = s;
    }

    public Snapshot Current { get { return _current; } }

  }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top