2

我有一个多线程 C++ 应用程序,它在内存中保存一个复杂的数据结构(缓存数据)。

当我刚刚读取数据时,一切都很好。我可以拥有任意数量的线程来访问数据。

然而,缓存的结构不是静态的。

  • 如果请求的数据项不可用,它将从数据库中读取,然后插入到数据树中。这可能也没有问题,即使我在将新数据项添加到只需要几个周期的树中使用互斥锁(它只是添加一个指针)。
  • 有一个不时执行的垃圾收集过程。它从树中删除所有旧项目。为此,我需要锁定整个事情以确保当前没有其他进程正在访问任何将从内存中删除的数据。当我从缓存中读取数据时,我还必须锁定树,这样我就不会在处理项目时删除它们(有点“相反的事情”)。

“伪代码”:

function getItem(key)
   lockMutex()
   foundItem = walkTreeToFindItem(key)
   copyItem(foundItem, safeCopy)
   unlockMutex()
   return safeCopy
end function

function garbageCollection()
   while item = nextItemInTree
      if (tooOld) then
         lockMutex()
         deleteItem(item)
         unlockMutex()
      end if
   end while
end function

困扰我的是:这意味着,我必须在阅读时锁定树(以避免在阅读时开始垃圾收集)。但是 - 作为副作用 - 我也不能同时拥有两个阅读过程。

有什么建议么?

是否有某种“这是一个只读操作,只与写入冲突”互斥锁?

4

4 回答 4

11

查看read-write-lock

您没有指定可以使用哪个框架,但pThreadboost都实现了该模式。

于 2009-10-21T16:26:13.537 回答
4

正如其他人所说,这个概念是“共享阅读器,单一作者”锁。在 Linux 环境中,您应该能够在pthread_rwlock_t没有任何框架的情况下使用。我建议也调查一下boost::shared_lock

于 2009-10-21T16:32:35.813 回答
3

我建议使用reader-writer lock。这个想法是你可以获得一个“读”或“写”的锁,锁将允许多个读者,但只允许一个写者。非常便利。

于 2009-10-21T16:26:40.790 回答
0

在 C++17 中, std::shared_mutex直接支持这种类型的访问(多读、单写)。我认为这是从 boost::shared_lock 采用的。该主题还在 Anthony Williams 的 C++ Concurrency in Action 中通过示例进行了描述。 https://livebook.manning.com/book/c-plus-plus-concurrency-in-action-second-edition/chapter-3/185

基本位是:

  • 在允许共享访问的读取上使用 std::shared_lock
    • 现有的 shared_locks 不会阻止新的 shared_lock 锁定
  • 在需要独占访问的更新/写入函数上使用 std::unique_lock
    • 将等到所有现有的共享读取以及其他写入完成
    • 在锁定时排除任何其他读取或写入
于 2019-11-30T14:36:48.680 回答