我正在进入的情况下,我需要在存储器中的两个值的原子总和。我继承的代码是这样的:

int a = *MemoryLocationOne;
memory_fence();
int b = *MemoryLocationTwo;
return (a + b) == 0;

在个体的a和b是原子读取,并在代码这两个存储位置的其他地方的所有写入也无锁原子。然而,问题在于,这两个位置的值可以并且确实之间的两次读取改变。

那么,如何使这个操作原子?我知道所有关于CAS,但它往往只涉及使读 - 修改 - 写操作原子和这并不完全是我想在这里做的。

有没有办法做到这一点,或者是重构代码,这样我只需要检查一个值的最佳选择?

编辑:谢谢你,我没有提到,我想在第一次修订locklessly做到这一点,但有些人我第二次修订后拿起它。我知道,当他们说这样的事情没有人相信的人,但我不能实际使用锁。我不得不仿效与原子能互斥,并且会是比重构代码,以保持一个值的轨道,而不是两个更多的工作。

现在我调查的方法包括利用的事实,值是连续的,并与64位读,我敢保证原子抓住他们都是我的目标平台的原子。如果任何人有新的想法,请贡献!感谢。

有帮助吗?

解决方案

如果你真的需要确保ab,而你正在做这个测试不改变,那么你需要使用全部访问ab相同的同步。这是你唯一的选择。每一读取和每个写入这些值之一需要使用相同的存储器围栏,同步器,信号量,时间片锁,或任何机构被使用。

通过此,可以保证,如果:

memory_fence_start();
int a = *MemoryLocationOne;
int b = *MemoryLocationTwo;
int test = (a + b) == 0;
memory_fence_stop();

return test;

那么当你正在阅读a b不会改变。但同样,你必须使用相同的同步机制的所有的访问ab

要反映在以后编辑你的问题,你正在寻找一个无锁的方法,那么,这完全取决于你所使用的处理器和ab有多长和对这些存储单元是否是连续和正确对准

假设这些是在存储器中,并且每个32位连续的,并且您的处理器具有的原子的64位的读取,则可以发出一个原子的64位读出到读出在两个值,解析所述两个值从64的位价值,做数学题,返回你想回到什么。假设你永远不需要孤立的原子更新为“ab在同一时间”,但只有原子更新为“a”或“b”,那么这将做你想做的没有锁。

其他提示

您必须确保无处不在任两个值被读出或写入,它们是由一个存储器屏障(锁定或关键部分)包围。

// all reads...
lock(lockProtectingAllAccessToMemoryOneAndTwo)
{
    a = *MemoryLocationOne;
    b = *MemoryLocationTwo;
}

...

// all writes...
lock(lockProtectingAllAccessToMemoryOneAndTwo)
{
    *MemoryLocationOne = someValue;
    *MemoryLocationTwo = someOtherValue;
}

如果你的目标86,可以使用64位比较/交换支持和包装都INT的成单64位字。

在Windows中,你可以这样做:

// Skipping ensuring padding.
union Data
{
     struct members
     {
         int a;
         int b;
     };

     LONGLONG _64bitData;  
};

Data* data;


Data captured;

do
{
    captured = *data;
    int result = captured.members.a + captured.members.b;
} while (InterlockedCompareExchange64((LONGLONG*)&data->_64bitData,
                    captured._64BitData,
                    captured._64bitData) != captured._64BitData);

真难看。我建议使用锁 - 更容易维护。

编辑: 更新和读出的单个部件:

data->members.a = 0;
fence();

data->members.b = 0;
fence();

int captured = data->members.a;

int captured = data->members.b;

有真的是没有办法做到这一点没有锁。没有处理器具有双原子读,因为据我所知。

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