【发布时间】:2013-12-01 04:20:23
【问题描述】:
以下类的问题是在读取myThreadSafe.Value 时,它可能不会返回最新的值。
public class ThreadSafe
{
private int value;
public int Value { get { return value; } }
public void Update()
{
Interlocked.Add(ref value, 47); // UPDATE: use interlocked to not distract from the question being asked.
}
}
我意识到我可以在读取和写入时锁定:
public int Value { get { lock(locker) return value; } }
public void Update()
{
lock(locker)
{
value += 47;
}
}
而且我一直遵循这种使用锁的模式。但是,我正在尝试减少代码中的锁数量(有很多,而且它们被频繁调用,我已经分析过,Montior.Enter() 占用的时间比我想的要多 - 因为它被调用了很多次)。
更新:我现在想知道锁定是否确实会在确保我读取最新值方面产生任何影响,它仍然可能来自机器的 CPU 缓存之一不能它? (所有的锁保证都是互斥线程访问)。
我认为volatile 会是答案,MSDN 确实说:“这确保该字段中始终存在最新的值”,但是我读了elsewhere 写然后读使用 volatile 时仍然可以交换 CPU 指令,在这种情况下,我可以获得 myThreadSafe.Value 的先前值,也许我可以忍受 - 只有一次更新。
让我始终获得myThreadSafe.Value 最新值的最有效方法是什么?
更新:此代码将在 CPU 架构上编译和运行:
- x86
- AMD64(虽然我可以构建为 x86)
- PowerPC
- ARM(仅限小端)
使用运行时:
- CLR v4.0
- Mono(我不确定 Mono 运行时版本,但如果它们对应于 Mono 版本:至少 3.0)。
我希望对所有构建都使用相同的代码!
【问题讨论】:
-
您多久写入一次值与读取一次?
-
Interlocked 的方法对你有用吗?
-
我认为你需要看看
ReaderWriterLock类。在我看来,您有多个读者,但只有一个作者。 -
我可以从 ThreadPool 中的任何线程写入,即调用 Update(),最多每秒 100 次。我将每秒阅读一个线程 60 次。
-
@HansPassant :) 我开始倾向于坚持使用锁定并减少调用次数,但是我现在担心锁定事件是否保证我正在读取相同的值?如果它被缓存在一个 CPU 中,它会使缓存失效吗?
标签: c# .net multithreading .net-4.0 thread-safety