以线程安全的方式返回指针

时间:2010-04-19 21:00:52

标签: c++ pointers thread-safety

假设我有一个线程安全的Things集合(称之为ThingList),我想添加以下函数。

Thing * ThingList::findByName(string name)
{
  return &item[name]; // or something similar..
}

但是通过这样做,我已经将线程安全的责任委托给调用代码,调用代码必须执行以下操作:

try 
{
  list.lock(); // NEEDED FOR THREAD SAFETY
  Thing *foo = list.findByName("wibble");
  foo->Bar = 123;
  list.unlock();  
}
catch (...) 
{
  list.unlock();
  throw;
} 

显然,RAII锁定/解锁对象会简化/删除try / catch / unlocks,但调用者仍然很容易忘记。

我看过几个替代方案:

  • 按值返回,而不是 指针 - 除非您需要,否则很好 修改事情
  • 添加函数ThingList::setItemBar(string name, int value) - 很好,但这些往往 增殖
  • 返回一个类似指针的对象,该对象在创建时锁定列表,并在销毁时再次解锁。不确定这是好事还是坏事......

处理这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:4)

没有一个“正确的方法”;这取决于您的应用程序的需求。

如果可能,按值返回内容,或返回调用者可以随意执行的任何副本。

上述的一个变体是返回一个可修改的副本,然后提供一种将修改后的对象原子合并回列表的方法。类似的东西:

Thing t = myThingList.getThing(key);
t.setFoo(f);
t.setBar(b);
myThingList.merge(t);     // ThingList atomically updates the appropriate element

但是,如果多个线程尝试更新同一个对象,则会导致问题。

“指针式对象”的想法听起来很酷,但我怀疑当某些锁没有被释放时,它会导致难以发现的错误。

我会尝试将所有锁定/解锁代码保留在ThingList内,因此ThingList::set...函数可能就是我要做的。

答案 1 :(得分:3)

存储并返回boost :: shared_ptr s

你必须在访问期间锁定,但解锁后你是安全的