在两个主循环线程之间传递值的非阻塞和低延迟方法
本文关键字:方法 延迟 之间 两个 线程 循环线 循环 | 更新日期: 2023-09-27 18:35:26
在我的项目中,有一个以大约 86 fps 的速度更新的音频线程和一个以 60 fps 运行的图形线程。两个线程都可以相互生成和使用值。
但是没有必要使用每个值,只有最新的值很重要,不需要通知,因为线程只是在需要时请求一个新值。
在阅读了大量关于线程的网站后,我有点困惑我真正需要什么,因为我的任务非常简单。使用锁,我的代码如下所示:
private T aField; //memory location
//other thread reads value
public void ReadValue(ref T val)
{
lock(myLock) copy aField to val;
}
//this thread updates value
private void UpdateValue(T newVal)
{
lock(myLock) copy newVal to aField;
}
我的第一个问题是,这是否适用于没有任何锁的 float 或 int(<=32 位大小)等原始类型,因为副本只是一个原子赋值?
下一个想法是布尔的保护:
private T aField; //memory location
private volatile bool isReading;
private volatile bool isWriting;
//other thread reads value
public void ReadValue(ref T val)
{
isReading = true;
if(!isWriting) copy aField to val;
isReading = false;
}
//this thread updates value
private void UpdateValue(T newVal)
{
isWriting = true;
if(!isReading) copy newVal to aField;
isWriting = false;
}
对我来说看起来不错,但我很确定我错过了一些东西。我可以想到一种最坏的情况,即较快的线程读取而慢速线程想要写入。然后,快速线程将在下次再次读取旧值,因为未进行任何更新。
我还发现了一种非阻塞更新方法,但我想知道它是否以及如何帮助我:
static void LockFreeUpdate<T> (ref T field, Func <T, T> updateFunction)
where T : class
{
var spinWait = new SpinWait();
while (true)
{
T snapshot1 = field;
T calc = updateFunction (snapshot1);
T snapshot2 = Interlocked.CompareExchange (ref field, calc, snapshot1);
if (snapshot1 == snapshot2) return;
spinWait.SpinOnce();
}
}
延迟最低的最有效方法是什么?
对于您的情况,您不需要任何锁,只需将易失性添加到私有 T aField; 以防止任何可能的编译器优化