6

我做出以下推理,请告诉我它的错误(或正确):

“如果内联函数在调用函数的地方复制了代码,那么静态变量和局部变量对于调用它的每个函数都会复制,并且如果只有一个线程在运行同时调用内联函数的函数,那么代码是线程安全的”。

“而且,如果它对静态和全局变量没有帮助,那么它对创建临时变量的代码有帮助吗?”

谢谢

4

11 回答 11

29

不,你错了。对于静态变量,无论是否内联,实际上只有一个实例。内联函数对线程安全没有任何影响,无论哪种方式。

于 2009-04-13T11:50:05.720 回答
26

当您将函数声明为内联时,它只是对编译器的提示。静态变量在语言中有明确的定义。如果编译器确实内联函数,它仍然有义务在函数的所有实例之间保持静态变量共享。因此,它们将保持全球性,并且必须在 MT 环境中受到保护。

至于局部变量,除非它们在函数外部使用,否则无论函数是否内联,它们都是线程安全的。

于 2009-04-13T11:54:02.870 回答
6

每个线程都有自己的本地对象副本,因此无论您是否将其设为内联,它们都不会出现任何与线程相关的问题。

但是,如果您正在访问类的静态变量或成员变量,则与多线程相关的所有问题(损坏变量、丢失更新......)仍然存在,无论它是否是内联的。

于 2009-04-13T11:55:09.920 回答
3

内联和线程安全是正交的,即不相关的概念。

考虑这些函数:

int 阶乘(const int n)
{
  如果 (n <= 1)
  {
    返回 1;
  }

  返回阶乘(n - 1);
}

这个函数不能被内联,因为它是递归的,但它是完全线程安全的。

int factorial_2(int n)
{
  整数结果 = 1;

  而 (n > 1)
  {
    结果 *= n--;
  }

  返回结果;
}

这个函数可以被编译器内联,并且仍然是完全线程安全的。

整数引用计数;

无效的 DecRef()
{
  --引用计数;
}

无论编译器是否内联它,这个函数都不是线程安全的。

于 2009-06-09T17:58:51.957 回答
2

有(或者可能)错误的编译器为包含函数的每个内联复制静态变量。这不是预期的行为。

使用符合标准的编译器,无论内联如何,都可以保证每个静态变量都有一个实例,并且必须自己处理线程安全。

于 2009-04-13T11:52:12.813 回答
2

线程安全与内联无关。仅仅因为每个线程都执行相同代码的副本并不能保证访问共享数据的安全。在开始多线程编程之前,请务必阅读线程安全。

于 2009-04-13T15:27:39.067 回答
2

如果我是你,我不会在内联函数中使用静态变量。旧版本的 C++ 标准要求与当前版本不同的含义。

注意:历史答案。今天没用。

于 2009-04-13T15:49:22.180 回答
2

以前版本的 C++(和当前版本的 C)不承认线程的概念。它只是不是标准的一部分。所以依靠一些编译器优化来使你的代码线程安全并不是一个好主意。

于 2012-07-12T12:27:28.527 回答
1

内联对函数是否是线程安全的没有影响。例如:

inline void doTheThing()
{
   int a = 42; // this is thread safe, but it would be anyway
   vector<int> * answers = getTheAnswers(); // this is not thread safe
}

对 getTheAnswers() 指向的向量的访问不是线程安全的,因为没有代码阻止任何其他线程执行代码。使函数内联不会阻止 doTheThing() 被多个线程同时调用。为了使 doTheThing() 线程安全,您需要确保它不会被并行调用,或者您访问的任何共享(非本地)数据都受到保护。

于 2009-04-13T12:28:46.423 回答
0

一点也不。

为了线程安全,函数需要对函数的任何实例(包括它自己)都是线程安全的;多个线程可以同时执行内联函数的同一个实例。

因此,即使编译器执行了您的建议(正如其他人所说,它不应该这样做),这仍然不会使其成为线程安全的。

于 2009-04-13T17:12:25.773 回答
-3

(普通和内联)函数中的所有静态变量都进入堆。堆不是线程安全的。

于 2009-04-14T01:44:05.760 回答