我做出以下推理,请告诉我它的错误(或正确):
“如果内联函数在调用函数的地方复制了代码,那么静态变量和局部变量对于调用它的每个函数都会复制,并且如果只有一个线程在运行同时调用内联函数的函数,那么代码是线程安全的”。
“而且,如果它对静态和全局变量没有帮助,那么它对创建临时变量的代码有帮助吗?”
谢谢
我做出以下推理,请告诉我它的错误(或正确):
“如果内联函数在调用函数的地方复制了代码,那么静态变量和局部变量对于调用它的每个函数都会复制,并且如果只有一个线程在运行同时调用内联函数的函数,那么代码是线程安全的”。
“而且,如果它对静态和全局变量没有帮助,那么它对创建临时变量的代码有帮助吗?”
谢谢
不,你错了。对于静态变量,无论是否内联,实际上只有一个实例。内联函数对线程安全没有任何影响,无论哪种方式。
当您将函数声明为内联时,它只是对编译器的提示。静态变量在语言中有明确的定义。如果编译器确实内联函数,它仍然有义务在函数的所有实例之间保持静态变量共享。因此,它们将保持全球性,并且必须在 MT 环境中受到保护。
至于局部变量,除非它们在函数外部使用,否则无论函数是否内联,它们都是线程安全的。
每个线程都有自己的本地对象副本,因此无论您是否将其设为内联,它们都不会出现任何与线程相关的问题。
但是,如果您正在访问类的静态变量或成员变量,则与多线程相关的所有问题(损坏变量、丢失更新......)仍然存在,无论它是否是内联的。
内联和线程安全是正交的,即不相关的概念。
考虑这些函数:
int 阶乘(const int n) { 如果 (n <= 1) { 返回 1; } 返回阶乘(n - 1); }
这个函数不能被内联,因为它是递归的,但它是完全线程安全的。
int factorial_2(int n) { 整数结果 = 1; 而 (n > 1) { 结果 *= n--; } 返回结果; }
这个函数可以被编译器内联,并且仍然是完全线程安全的。
整数引用计数; 无效的 DecRef() { --引用计数; }
无论编译器是否内联它,这个函数都不是线程安全的。
有(或者可能有)错误的编译器为包含函数的每个内联复制静态变量。这不是预期的行为。
使用符合标准的编译器,无论内联如何,都可以保证每个静态变量都有一个实例,并且必须自己处理线程安全。
如果我是你,我不会在内联函数中使用静态变量。旧版本的 C++ 标准要求与当前版本不同的含义。
注意:历史答案。今天没用。
以前版本的 C++(和当前版本的 C)不承认线程的概念。它只是不是标准的一部分。所以依靠一些编译器优化来使你的代码线程安全并不是一个好主意。
内联对函数是否是线程安全的没有影响。例如:
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() 线程安全,您需要确保它不会被并行调用,或者您访问的任何共享(非本地)数据都受到保护。
一点也不。
为了线程安全,函数需要对函数的任何实例(包括它自己)都是线程安全的;多个线程可以同时执行内联函数的同一个实例。
因此,即使编译器执行了您的建议(正如其他人所说,它不应该这样做),这仍然不会使其成为线程安全的。
(普通和内联)函数中的所有静态变量都进入堆。堆不是线程安全的。