首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >难并行设计

难并行设计
EN

Stack Overflow用户
提问于 2010-01-21 10:18:56
回答 1查看 218关注 0票数 1

我有一个名为Root的类,它充当动态方法调用的某种电话簿:它包含指向对象的url键字典。当一个命令想要执行一个给定的方法时,它会用一个url和一些参数调用一个Root实例:

代码语言:javascript
复制
root_->call("/some/url", ...);

实际上,Root中的call方法看起来很接近于此:

代码语言:javascript
复制
// Version 0
const Value call(const Url &url, const Value &val) {
  // A. find object
  if (!objects_.get(url.path(), &target))
    return ErrorValue(NOT_FOUND_ERROR, url.path());
  }

  // B. trigger the object's method
  return target->trigger(val);
}

从上面的代码中,您可以看到这个“调用”方法并不是线程安全的:可以在A和B之间删除"objects_“对象,而且我们也不能保证在读取”“成员(字典)时不会更改它。

我想到的第一个解决办法是:

代码语言:javascript
复制
// Version I
const Value call(const Url &url, const Value &val) {
  // Lock Root object with a mutex
  ScopedLock lock(mutex_);

  // A. find object
  if (!objects_.get(url.path(), &target))
    return ErrorValue(NOT_FOUND_ERROR, url.path());
  }

  // B. trigger the object's method
  return target->trigger(val);
}

这很好,直到“target->触发器(Val)”是一个需要通过更改对象的url或插入新对象来更改根的方法。修改作用域和使用RW互斥体可能会有所帮助(读取比在Root上写的要多得多):

代码语言:javascript
复制
// Version II
const Value call(const Url &url, const Value &val) {
  // A. find object
  {
    // Use a RW lock with smaller scope
    ScopedRead lock(mutex_);
    if (!objects_.get(url.path(), &target))
      return ErrorValue(NOT_FOUND_ERROR, url.path());
    }
  }
  // ? What happens to 'target' here ?

  // B. trigger the object's method
  return target->trigger(val);
}

“目标”会怎么样?如何确保它不会在查找和调用之间被删除?

一些想法:对象删除可以在根中的消息队列中发布。但是,我们将需要另一个RW互斥锁删除完整的方法作用域,并使用一个单独的线程来处理删除队列。

这一切对我来说都很复杂,我不知道并行设计是否必须像这样,或者我只是没有正确的想法。

PS:代码是一个名为示波 (OpenSoundControl it)的开源项目的一部分。

EN

回答 1

Stack Overflow用户

发布于 2010-01-21 13:39:57

你这样做是走错路了。记住:你不能锁定数据,你只能阻止代码。您不能用本地定义的互斥保护“对象”成员。您需要在更改对象集合的代码中使用完全相同的互斥对象。当另一个线程执行call()方法时,它必须阻止该代码。互斥必须至少在类范围内定义。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2108355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档