【问题标题】:Is Wikipedia wrong about reentrancy?维基百科关于重入的问题是错误的吗?
【发布时间】:2016-12-11 02:07:45
【问题描述】:

https://en.wikipedia.org/wiki/Reentrancy_(computing)(截至 2016 年 12 月 9 日)声明以下代码是可重入的,尽管修改了全局变量,因为 swap 保持不变:

int t;

void swap(int *x, int *y)
{
    int s;

    s = t; // save global variable
    t = *x;
    *x = *y;

    // hardware interrupt might invoke isr() here!
    *y = t;
    t = s; // restore global variable
}

但是,如果swap 在任何其他数量的地方被打断怎么办?根据术语的定义,这个函数是可重入的吗?

顺便说一下,这篇文章在 SO 的其他地方被引用为来源——也许有人应该改进它。

【问题讨论】:

  • 那是假的 IMO。
  • 如果被中断,任何代码都可能使数据处于不一致状态。在任何情况下,示例都是线程 unsafe 交换。
  • @JonathanLeffler 至少有 3 人认为这篇文章是假的,但我没有因为大声疾呼?
  • 维基文章搞砸了。尚不清楚为什么在局部变量也可以提供服务时将全局变量用作瞬态变量。不需要全局数据。我建议您在其他地方寻找有关重入的信息。
  • 阿塔男孩!我在途中,因此之前的简短评论。

标签: c multithreading thread-safety reentrancy


【解决方案1】:

要回答这个问题,有必要观察到“可重入”是一个超载的术语,具有多种公认的含义,其中一些含义从“延伸”到“明显不正确”。

我会说该函数是同步(但不是异步)可重入的,当然不是线程安全的。这在这里相当空洞,因为它不调用任何其他函数,但如果它调用一个回调函数,然后可以回调到这个函数中,那将是有意义的。

如果正确使用volatile 类型,该函数可能是异步可重入的(但仍然不是线程安全的)。

【讨论】:

  • volatile 不保证原子性,这在此处是必需的。在“线程安全”的广义形式(即真正的并发,没有内存一致性协议)中,volatile 的保证太弱(这里是不好的建议),甚至单独的stdatomic.h 也可能不够(它可以使用作为更复杂结构的构建块,例如互斥体和信号量)。
  • @Olaf: volatile sig_atomic_t 会,正如volatile 的实现定义的细节更普遍。但这就是为什么我说“可能是”而不是“是”的原因。
  • 1) 您没有特别提到sig_atomic_t,而是笼统地提到volatile。 2) sig_atomic_tstdatomic 类型的前身,允许使用特定于实现的添加来保证原子性。不过,这不是voliatile 的问题,而是这种特定类型的问题。 3) volatile 单独用于其他类型的限定符似乎安全。它特别不保证异步重入(这意味着线程安全),仅仅是因为它不保证原子性。大多数单 CPU 系统甚至无法保证这一点。
  • 异步重入并不意味着线程安全。在具有阻塞信号能力的系统(例如符合 POSIX 的系统)上,通过阻塞关键部分周围的信号来实现函数的异步重入是微不足道的,否则这些关键部分将无法重入。通过屏蔽中断,同样适用于裸机。这对实现线程安全没有任何帮助。
  • FWIW,文章提供了自己对“可重入”的定义
【解决方案2】:

您知道这个swap() 函数是以故意伪造的方式编写的。即使为了说明概念,最好将t 设为具有static 存储类的局部变量。这样,我们可以假设 t 没有在其他地方修改。

乍一看,即使在执行期间发生中断,也可以从中断服务例程调用该函数,因为正如他们所提到的,swap 在退出时恢复其私有全局(无用)状态的值。对此,可以认为是可重入的(异步重入)。

对于更复杂的函数,即回调用户提供的代码,这样的回调是否可以依次调用该函数也是重入的标准(同步重入),但这里不适用于@ 987654326@ 不调用任何东西。

现在的问题是硬件变得相当棘手,除非您正在对简单的嵌入式处理器进行编程,否则在中断例程中摆弄全局变量可能会产生令人惊讶的副作用。 t 应设为 volatile 以防止其中一些,但不是全部。

附带说明,如果 swap() 被不同的抢占线程调用,调用和返回序列可能会交错,这种情况不是由函数处理的,更不用说访问全局变量 @ 987654330@ 不保证是原子的...swap 绝对不是线程安全的。

【讨论】:

  • 您的回答甚至没有提到“reentr”。我不认为函数的线程安全是有争议的。
  • @MaxB:我重新表述了我的答案以强调可重入性方面,并将多线程问题作为旁注。这些问题通常被许多程序员混淆,将它们进行对比会很有用。
猜你喜欢
  • 1970-01-01
  • 2011-04-16
  • 2021-04-20
  • 2018-05-27
  • 2014-11-14
  • 2017-07-06
  • 2010-10-12
相关资源
最近更新 更多