Multithreading 从锁/信号量内调用操作

Multithreading 从锁/信号量内调用操作,multithreading,Multithreading,我有一个接受动作的函数。该函数获取一个信号量锁(但就问题而言,也可以是监视器锁),然后调用该操作 一位代码审阅者指出,这并不代表实现线程安全的有效方法,因为它容易受到致命的攻击。线程安全代码应该被封装,但您可以通过允许第三方调用外部操作来打破这一点。(这就像在锁中引发事件一样。) 忽略封装位,是否存在使用锁从调用操作的特殊情况?我的直觉是,一个操作不会比任何其他代码更容易导致死锁,但在我提出质疑之前,他是对的吗?在获得锁时调用外部代码的问题是,您无法再保证您的代码是死锁安全的 调用方可以在回调操

我有一个接受动作的函数。该函数获取一个信号量锁(但就问题而言,也可以是监视器锁),然后调用该操作

一位代码审阅者指出,这并不代表实现线程安全的有效方法,因为它容易受到致命的攻击。线程安全代码应该被封装,但您可以通过允许第三方调用外部操作来打破这一点。(这就像在锁中引发事件一样。)


忽略封装位,是否存在使用锁从调用操作的特殊情况?我的直觉是,一个操作不会比任何其他代码更容易导致死锁,但在我提出质疑之前,他是对的吗?

在获得锁时调用外部代码的问题是,您无法再保证您的代码是死锁安全的

调用方可以在回调操作中执行任何操作。
以下是一些可能执行“危险”操作的示例:

  • 函数的递归调用。在这种情况下,死锁是可能的
  • 执行一些长时间运行的操作。如果其他线程需要相同的同步对象(监视器或信号量),这可能会降低它们的性能
  • 我相信也有可能出现其他负面情况

    监视器(或信号量)的目的是防止同时进入代码段,而代码段绝对不应同时运行。回调操作并非如此。
    因此,没有充分的理由在锁内调用操作


    在这里,我建议在获取锁之前或释放锁之后调用回调操作。

    我认为这个问题更适合于,因为它询问的是软件设计。在堆栈溢出上,它只是基于
    主要意见的
    一个。这与设计和外部操作相关的责任更相关。锁是通过某个处理程序操纵的,因此为了再次获取锁(导致死锁),该处理程序必须可用于外部操作。这很容易避免-例如,不向触发外部操作的函数提供锁处理程序。@SomeWittyUsername私有处理程序可以被重新获取,即使它对于外部代码不可见。只需对函数进行第二次调用,即可获得该函数。这可以通过回调操作完成。没有任何东西可以完全防止bug。实际上不需要外部操作来实现死锁。例如,在获得锁后,您可以简单地对正在执行的函数进行递归调用。锁定函数的编写应确保在从外部回调操作执行递归调用时是安全的。这就是为什么在锁中调用外部代码是不好的。控件是一个定义问题。正确的外部操作应具备一系列先决条件。安全递归调用取决于所使用的锁定机制的类型。如果本地再入是安全的,那么从外部动作(或直接锁重新获取)再入也是安全的,反之亦然