【问题标题】:How to do a "try_lock" with an "upgrade_to_unique_lock"如何使用“upgrade_to_unique_lock”执行“try_lock”
【发布时间】:2011-07-27 23:37:55
【问题描述】:

我想在没有阻塞的情况下对 upgrade_lock 执行 upgrade_to_unique_lock,但粗略查看 Boost 源代码 (v1.46.1) 表明这是不可能的?我的方法错了吗?

我想首先获得一个资源的读锁,该资源也可能被其他线程持有以供读取。然后我想看看它是否可以写入,如果没有(其他共享读锁当前持有它),稍后再做。

// No way to specify the boost::try_to_lock object
explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
    source(&m_),exclusive(move(*source))

我正在尝试异步使用中点置换算法在程序上无缝地生成地形图块(页面)。这需要使用从周围 4 个瓷砖(北、西、东、南)获得的边缘来播种主题地形图块(中心)。边缘仅从存在且已完全生成的邻居中收集。实现应该一次阻塞一个邻居块,而不是持有其他邻居的读锁,以便随时生成释放它们。生成瓦片时,它必须保证没有其他线程对其邻居有写锁,读锁是可以的。此外,不应该有一个菊花链线程不必要地等待写锁(即距离相隔两个瓷砖的瓷砖应该能够相互独立地生成)。

我的实现依赖于第三方算法,该算法根据与相机的观看距离根据需要异步请求页面。看起来它可以任意对页面/图块进行 16 个异步请求,不分先后。

【问题讨论】:

  • Then I want to see if it is available for writing and if not (other shared read locks are currently held on it) simply do it later.
  • 参见:home.roadrunner.com/~hinnant/bloomington/shared_mutex.html 我是upgrade_mutex 的发明者。规范在 boost 实现中被破坏了。我提供的链接提供了一个规范,可以满足您的需求。我正在尝试将此规范纳入下一个 C++ 标准(可能首先纳入技术报告)。如果这个规范对你来说很好,那就大声疾呼吧。让您的国家机构代表知道这就是您想要的。让这群人知道这是你想要的。让 comp.std.c++ 的人群知道。如果不是您想要的,请告诉我。
  • 你用这个资源做什么?想要尝试做某事,而如果您不能做其他事情,这似乎很奇怪。你有没有回到重试?如果您有更具体的建议,也许我们可以提出更好的方法。
  • @Howard:我真的很惊讶它已经不在标准中,我认为它已经是。 :o
  • 这可能是我可以使用一些见解的地方。我正在尝试以原子方式制作 4 个读锁(北、东、南、西)并升级 1 个读写锁(中心)。所以基本上我想在一个主锁内做 5 次尝试锁,如果其中任何一个失败,那么所有锁都会被释放,然后是主锁。应该只有两种状态:获得 4 个读锁和 1 个升级的写锁或根本没有。太复杂了,我不喜欢,但我没有其他想法。

标签: c++ boost locks


【解决方案1】:

稻草人回答。我很确定这不是一个有效的答案。但由于格式问题,我无法将其放在评论中。

要生成中心图块,我很想这样做:

tile::generate_center()
{
    tile& north = ...;
    tile& east = ...;
    tile& south = ...;
    tile& west = ...;
    std::unique_lock<mutex_type> l0(mutex(), std::defer_lock);
    shared_lock<mutex_type> ln(north.mutex(), std::defer_lock);
    shared_lock<mutex_type> le(east.mutex(), std::defer_lock);
    shared_lock<mutex_type> ls(south.mutex(), std::defer_lock);
    shared_lock<mutex_type> lw(west.mutex(), std::defer_lock);
    std::lock(l0, ln, le, ls, lw);
    // This is exclusively locked, neighbors are share locked
    // ...
}

这是使用 C++11 位,例如 std::unique_lock 和 std::defer_lock。我相信你也可以从 boost 中获得这个功能(虽然不是积极的)。

此例程以原子方式独占锁定中心,并共享锁定邻居。它阻塞,直到它可以得到所有的锁。它不会阻止它的邻居做同样的事情。也就是说,使用std::lock 将确保没有死锁。

我非常不确定这实际上是在解决您正在尝试做的事情。但也许它会帮助你找到答案......

【讨论】:

  • 这基本上就是我最终得到的结果,除了我没有使用 std::lock 因为我认为我没有那个功能。该方法有效,但无法打破或陷入僵局。
  • 如果您没有std::lock,请尝试boost::lock。如果两个相邻的图块尝试同时生成,则此代码将死锁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多