2017-05-01 34 views
0

我有以下函数updateEntry它将值写入查找表。我想创建这个函数的多线程版本。 我正在研究原子操作__sync_bool_compare_and_swap,但我不知道如何在这里正确应用它。原子功能没有锁来改变两个独立的存储位置

是否理论上可以在没有锁定的情况下自动实现此功能,因为它会更改两个独立的存储位置entryLookup[id]entry

void updateEntry(Entry ** entryLookup, unsigned int id, int val1, short val2){ 
      Entry * entry  = entryLookup[id]; 
      entry->val1  = val1; 
      entry->val2  = val2; 
      entryLookup[id] += sizeof(Entry); 
    } 
+1

问题:1)您能否确保每个线程都会访问不相交的'id'集? 2)你能确保修改'val1'和'val2'永远不会影响'entryLookup'运算符[]'的结果吗? 3)你能确保修改'entryLookup'的值不会影响任何并行线程(例如新的id不被任何其他线程访问)吗?如果这些规则中的任何一个不匹配,我看到实施无锁并发的困难。 –

+0

@AdrianMaire非常感谢您的回答。我建立了一个解决方案,使用不相交的id集合,但生成这种不相交的集合是昂贵的。我想避免使用不相交的ID集。第2点中的意思是什么?)? –

+1

Q4 - 更新是否与查找一致?如果没有,你可以首先原子更新'entryLookup [id]',确保没有其他线程会使用同一个条目,然后更新你的闲暇时间(有点)。如果查找也发生,则必须将两个单独的位置一起更新,这是使用原始原子操作无法完成的。 – eran

回答

1

为了使这个线程安全的,你可以增加entryLookup[id]首先要确保是后不能更改相同的条目,然后填入值的任何其他线程。在返回旧值时需要添加原子:

void updateEntry(Entry ** entryLookup, unsigned int id, int val1, short val2) 
{ 
    Entry * entry = __sync_fetch_and_add(&entryLookup[id], sizeof(Entry)); 
    entry->val1 = val1; 
    entry->val2 = val2; 
} 
+0

我刚刚注意到@eran已经在评论中给出了这个答案。 – peppincsoda

+0

这很简单,应该解决我的问题。非常感谢这个伟大的答案。 –

+0

@peppincsoda这里的问题是,'val'条目的修改从不被释放(同步)。你怎么能安全地访问另一个线程中的'entry'? – LWimsey