【发布时间】:2010-03-19 10:37:29
【问题描述】:
我必须设计一个要在多线程环境中使用的数据结构。基本 API 很简单:插入元素、删除元素、检索元素、检查元素是否存在。该结构的实现使用隐式锁定来保证单个 API 调用的原子性。在我实现这个之后,很明显,我真正需要的是跨多个 API 调用的原子性。例如,如果调用者需要在尝试插入元素之前检查元素是否存在,即使每个单独的 API 调用 都是原子的,他也不能原子地执行此操作:
if(!data_structure.exists(element)) {
data_structure.insert(element);
}
这个例子有点尴尬,但基本的一点是,在我们从原子上下文返回后,我们不能再相信“存在”调用的结果(生成的程序集清楚地显示了两次调用之间的上下文切换的可能性很小)。
我目前想解决这个问题的是通过数据结构的公共 API 公开锁。这样,客户将不得不显式地锁定事物,但至少他们不必创建自己的锁。对于这类问题,是否有更好的众所周知的解决方案?只要我们还在,您能推荐一些关于线程安全设计的优秀文献吗?
编辑:我有一个更好的例子。假设元素检索返回一个引用或指向存储元素的指针,而不是它的副本。调用返回后,如何保护调用者安全地使用此指针\引用?如果您认为不返回副本是个问题,那么请考虑深副本,即对象还应该复制它们在内部指向的另一个对象。
谢谢。
【问题讨论】:
-
关于您的编辑:想想这种情况,指向存储元素的指针返回,而其他线程试图从 data_structture 中删除该元素。无论 oof 锁定模型,您至少需要选择应该实现的行为。向试图删除对象的线程返回错误?等待对象变为未引用等。
标签: multithreading synchronization data-structures