是否有C++设计模式实现控制线程拥有锁定资源的时间量的机制或互斥体?

Jay*_*ton 16 c++ mutex deadlock

我正在寻找一种方法来保证线程锁定特定资源的任何时候,它被强制在特定时间段之后释放该资源(如果它还没有释放它).设想一个连接,您需要限制任何特定线程可以拥有该连接的时间.

我设想这是如何使用它:

{
    std::lock_guard<std::TimeLimitedMutex> lock(this->myTimeLimitedMutex, timeout);
    try {
        // perform some operation with the resource that myTimeLimitedMutex guards. 
    }
    catch (MutexTimeoutException ex) {
        // perform cleanup
    }
}
Run Code Online (Sandbox Code Playgroud)

我看到有一个timed_mutex,如果无法获取锁,程序会超时.我需要在获取锁之后发生超时.

在某些情况下,您可以获得可以意外删除的资源.例如,tcp套接字 - 一旦建立套接字连接,每一侧的代码都需要处理另一方丢弃连接的情况.

我正在寻找一种处理通常超时的资源类型的模式,但是当它们没有时,它们需要被重置.这不必处理每种类型的资源.

Ser*_*eyA 32

这不起作用,它永远不会起作用.换句话说,永远不可能做到这一点.它违背了所有权和原子交易的所有概念.因为当线程获取锁并在一行中实现两个事务时,它期望它们对于外部单词在原子上可见.在这种情况下,交易很可能会被撕裂 - 第一部分将被执行,但第二部分将不会执行.

更糟糕的是,由于锁定将被强制删除,在被中断的线程有机会回滚之前,部分执行的事务将对外部字体可见.

这个想法与所有多线程思维学派相悖.

  • 用于更新共享资源的一些机制(例如比较和交换)可以处理"回滚"而不会中断线程必须执行任何操作.使用锁进行仲裁可能会提供比线程尝试更新最终失败更好的性能,但强行从更新它的线程中窃取对象只会损害性能,而不是正确性. (5认同)

Joh*_*ann 15

我支持谢谢谢谢.超时后释放锁定的互斥锁是个坏主意,无法正常工作.Mutex代表互斥,这是一个不容易违反的坚硬合同.

但你可以做你想做的事:

问题:您希望保证线程不会将互斥锁保持的时间超过特定时间T.

解决方案:永远不要锁定互斥锁的时间超过时间T.而是编写代码,以便仅为绝对必要的操作锁定互斥锁.总是可以给出这样的时间T(当然,根据我的多任务处理和多用户操作系统来模拟不确定性和限制).

为此(例子):

  • 切勿在锁定的部分内进行文件I/O.
  • 永久锁定互斥锁时,切勿呼叫系统呼叫.
  • 在互斥锁被锁定时避免对列表进行排序(*).
  • 当互斥锁被锁定(*)时,避免对列表的每个元素执行慢速操作.
  • 在互斥锁被锁定(*)时避免内存分配/释放.

这些规则有例外,但一般准则是:

  • 使您的代码略微不太理想(例如在临界区内进行一些冗余复制),以使关键部分尽可能短.这是很好的多线程编程.

(*)这些只是操作的例子,它很有可能锁定整个列表,执行操作然后解锁列表.相反,建议只需获取列表的本地副本并在互斥锁被锁定时清除原始列表,理想情况是使用swap()大多数STL容器提供的操作.然后在关键部分之外的本地副本上执行慢速操作.这并非总是可行,但总是值得考虑.在最坏的情况下,排序具有方形复杂性,并且通常需要随机访问整个列表.在临界区之外对列表进行排序(副本)以及稍后检查是否需要添加或删除元素非常有用.内存分配也背后有一些复杂性,因此应避免大量内存分配/解除分配.


xry*_*669 5

你不能只用C++做到这一点.

如果您使用的是Posix系统,则可以完成.你必须触发一个SIGALARM信号,该信号只对那些超时的线程进行掩码.在信号处理程序中,您必须设置一个标志并用于longjmp返回线程代码.在线程代码中,在setjmp位置上,只有在触发信号时才能调用,因此可以抛出Timeout异常.

请参阅此答案以了解如何执行此操作.

此外,在linux上,似乎你可以直接从信号处理程序抛出(所以这里没有longjmp/setjmp).

顺便说一句,如果我是你,我会编写相反的代码.想一想:你想告诉一个帖子"嘿,你花了太长时间,所以让我们抛弃你迄今为止所做的所有(长期)工作,这样我就可以取得进步".理想情况下,你应该让你的长线程更合作,做一些类似"我已经完成了ABCD任务的事情,让我们释放互斥锁,以便其他人可以在A上进行.然后让我们检查一下是否可以再次使用它做B和等等." 你可能想要更细粒度(在较小的对象上有更多的互斥锁,但确保你以相同的顺序锁定)或使用RW锁(如果你不修改它们,其他线程可以使用这些对象),等等...