我有一些数据是由多个线程读取和更新。读取和写入都必须是原子的。我想这样做是这样的:无锁读写器
// Values must be read and updated atomically
struct SValues
{
double a;
double b;
double c;
double d;
};
class Test
{
public:
Test()
{
m_pValues = &m_values;
}
SValues* LockAndGet()
{
// Spin forver until we got ownership of the pointer
while (true)
{
SValues* pValues = (SValues*)::InterlockedExchange((long*)m_pValues, 0xffffffff);
if (pValues != (SValues*)0xffffffff)
{
return pValues;
}
}
}
void Unlock(SValues* pValues)
{
// Return the pointer so other threads can lock it
::InterlockedExchange((long*)m_pValues, (long)pValues);
}
private:
SValues* m_pValues;
SValues m_values;
};
void TestFunc()
{
Test test;
SValues* pValues = test.LockAndGet();
// Update or read values
test.Unlock(pValues);
}
的数据被窃取的指针,它保护每一个读取和写入,这应该使线程安全的,但它需要每一个访问提供了两个互锁的指令。将有大量的读取和写入,并且我不能预先告知是否会有更多的读取或更多的写入。
它可以做得比这更有效吗?这在阅读时也会锁定,但由于可能有更多的写入,所以阅读没有任何优化阅读的意义,除非它不会对写作造成损失。
我正在考虑在没有互锁指令(连同序列号)的情况下获取指针的读取操作,复制数据,然后有一种方法告诉序列号是否已更改,在这种情况下应该重试。但是,这需要一些记忆障碍,我不知道它是否能够提高速度。
-----编辑-----
感谢所有的好评!我实际上没有运行这个代码,但我会尝试今天晚些时候将当前方法与关键部分进行比较(如果我获得时间)。我仍然在寻找最佳的解决方案,所以稍后我会回到更高级的评论。再次感谢!
什么是使用默认的线程同步原语的问题? – naivnomore 2010-07-29 06:29:07
我必须承认,我只是假设我能做得更快。 1)我只在这里显示一个实例,但实际上我可能会有这些受保护的数据记录的10000个实例,这将意味着10000个关键部分。但也许这不是问题,我不知道,我从来没有尝试过这样的事情。 2)我希望我能拿出比关键部分更快的东西。每秒可以轻松实现数百万次读/写。而在个人层面上,我认为让它像人性化(机器化)一样快是有趣的。 – Rabbit 2010-07-29 06:49:06
Windows CRITICAL_SECTION非常轻便,除非实际上必须阻止。我不认为像这样忙着等待用户线程是一个非常好的主意 - 你隐式地告诉调度程序,你有很多事情要做,而实际上情况正好相反。 – 2010-07-29 07:46:54