2013-03-21 59 views
3

在我们的应用程序中,我们处理在工作线程中处理并在显示线程中访问的数据,并且我们有一个互斥体负责处理关键部分。没什么特别的。保护数据设计模式

现在我们考虑重新处理我们的代码,当前锁定由持有和处理数据的方明确地完成。我们想到了一个拥有数据的实体,只能以保护的方式访问数据。

为此,我们有一个名为GuardedData的类。调用者可以请求这样一个对象,并且应该在本地范围内只保留一小段时间。只要对象存在,它就会保持锁定状态。一旦对象被销毁,锁就会被释放。数据访问与锁定机制相结合,无需在调用者中进行任何明确的额外工作。班级的名字提醒现在的警卫的来电者。

template<typename T, typename Lockable> 
class GuardedData { 
    GuardedData(T &d, Lockable &m) : data(d), guard(m) {} 
    boost::lock_guard<Lockable> guard; 
    T &data; 

    T &operator->() { return data; } 
}; 

再次,一个非常简单的概念。运算符 - >模仿STL迭代器的语义以访问有效负载。

现在我不知道:

  • 是这种方法众所周知的?
  • 是否有像这样的模板类已经可用,例如:在boost库中?

我在问,因为我认为这是一个相当通用和可用的概念。虽然我找不到像这样的东西。

+1

我有数据可以在后台访问时在前台进行更改。有效地,当背景计算完成时,数据被交换。当有人访问数据时,这种交换不应该发生,这可能导致该方进入不一致的状态。我们需要做交换而不是创建一个新的实例,而其他人仍然使用旧的实例。原因是同时驻留在内存中的大量数据。 – ypnos 2013-03-21 13:59:12

回答

1

众所周知,我不确定。但是,我在Qt中使用了类似的机制,通常称为QMutexLocker。这个区别(小的一个,imho)是你将数据和互斥锁绑定在一起。与您所描述的机制非常类似的机制是C#中线程同步的标准。

您的方法很适合一次监视一个数据项,但如果您需要保护更多,则会变得很麻烦。此外,它看起来并不像你的设计会阻止我在共享位置创建这个对象,并且经常访问数据,认为它被完全保护好了,但实际上递归访问的场景不会被处理,也不会被处理多线程访问方案(如果它们出现在相同范围内)。

这个想法似乎有一点点的脱节。它的使用传达给我的是,访问数据始终是线程安全的,因为数据是被保护的。通常,这不足以确保线程安全。受保护数据的操作顺序通常很重要,因此锁定实际上是面向范围的,而不是数据导向的。你可以通过守护一个虚拟对象并将你的守护对象包装在一个临时范围中来解决这个问题,但为什么不仅仅使用一个现有的互斥体实现呢?

真的,这不是一个坏的方法,但你需要确保它的预期用途被理解。

+0

我认为QMutexLocker与boost :: lock_guard本身相同。它们都是互斥量/版本的RAII/RRID封装。 – Pete 2013-03-21 15:25:46

2

根据使用方法的不同,几乎可以保证在某个时刻结束死锁。如果你想操作2段数据,那么你最终会锁定互斥锁两次并发生死锁(除非每段数据都有自己的互斥锁 - 如果锁定顺序不一致,这也会导致死锁 - 你无法控制用这个方案不会让它变得非常复杂)。除非你使用可能不需要的递归互斥体。

另外,你的GuardedData对象是如何传递的?boost :: lock_guard不可复制 - 它会引发互斥体的所有权问题,即发布时的所有权问题&。

它可能更容易将您需要的部分数据复制到读写器线程,并在需要时将其保留在关键部分中。作者将同样致力于数据模型。

本质上,您的查看器线程可以在给定的时间获取所需数据的快照。这甚至可能完全适合位于正在运行线程的核心附近的cpu高速缓存,并且永远不会将其放入RAM中。编写器线程可能在读者正在处理它时修改底层数据(但应该使视图无效)。但是,由于观众有一个副本,它可以继续,并在与数据同步时提供数据视图。

另一种选择是给视图一个智能的数据指针(它应该被视为不可变的)。如果作者希望修改数据,则在此时复制数据,修改副本并在完成时将指针切换到模型中的数据。这将需要在处理时阻止所有读者/作者,除非只有一个作者。读卡器下一次请求数据时,会得到新的副本。

+0

所以第二次迭代是使用boost :: recursive_mutex而不是lock_guard。 – ypnos 2013-03-21 14:24:06

+0

有问题的数据对象可能达到几千兆字节,因此避免冗余副本很重要。 – ypnos 2013-03-21 14:25:15

+0

您是否需要每次都复制所有数据?允许外部客户管理锁定很可能最终会出现问题。 – Pete 2013-03-21 15:05:29