C++:多线程程序中的静态变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4590626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:51:28  来源:igfitidea点击:

C++: Static variables in multithreaded program

c++multithreadingstatic

提问by

What is the problem with having static variables (especially within functions) in multithreaded programs?

在多线程程序中使用静态变量(尤其是在函数中)有什么问题?

Thanks.

谢谢。

采纳答案by asveikau

To pick an illustrative example at random, take an interface like asctimein the C library. The prototype looks like this:

要随机选择一个说明性示例,请使用asctimeC 库中的接口。原型看起来像这样:

 char *
 asctime(const struct tm *timeptr);

This implicitly must have some global buffer to store the characters in the char*returned. The most common and simple way to accomplish this would be something like:

这隐含地必须有一些全局缓冲区来存储char*返回的字符。完成此操作的最常见和最简单的方法是:

 char *
 asctime(const struct tm *timeptr)
 {
    static char buf[MAX_SIZE];

    /* TODO: convert timeptr into string */

    return buf;
 }

This is totally broken in a multi-threaded environment, because bufwill be at the same address for each call to asctime(). If two threads call asctime()at the same time, they run the risk of overwriting each other's results. Implicit in the contract of asctime()is that the characters of the string will stick around until the next call to asctime(), and concurrent calls breaks this.

这在多线程环境中完全被破坏,因为buf每次调用asctime(). 如果两个线程同时调用asctime(),它们就有覆盖彼此结果的风险。的契约中隐含的asctime()是,字符串的字符将一直存在,直到下一次调用asctime(),并发调用打破了这一点。

There are some language extensions that work around this particular problem in this particular example via thread-local storage (__thread,__declspec(thread)). I believe this idea made it into C++0x as the thread_localkeyword.

在此特定示例中,有一些语言扩展可通过线程本地存储 ( __thread, __declspec(thread))解决此特定问题。我相信这个想法使它成为 C++0x 作为thread_local关键字。

Even so I would argue it's a bad design decision to use it this way, for similar reasons as for why it's bad to use global variables. Among other things, it may be thought of as a cleaner interface for the caller to maintain and provide this kind of state, rather than the callee. These are subjective arguments, however.

即便如此,我认为以这种方式使用它是一个糟糕的设计决定,原因与使用全局变量的原因类似。除其他外,它可以被认为是调用者维护和提供这种状态的更干净的接口,而不是被调用者。然而,这些都是主观的论点。

回答by James McNellis

Initialization is not thread-safe. Two threads can enter the function and both may initialize the function-scope static variable. That's not good. There's no telling what the result might be.

初始化不是线程安全的。两个线程可以进入函数,并且都可以初始化函数作用域的静态变量。这不好。不知道结果会怎样。

In C++0x, initialization of function-scope static variables will be thread-safe; the first thread to call the function will initialize the variable and any other threads calling that function will need to block until that initialization is complete.

在 C++0x 中,函数作用域静态变量的初始化将是线程安全的;调用该函数的第一个线程将初始化该变量,调用该函数的任何其他线程都需要阻塞,直到该初始化完成。

I don't think there are currently any compiler + standard library pairs that fully implement the C++0x concurrency memory model and the thread support and atomics libraries.

我认为目前没有任何编译器 + 标准库对完全实现 C++0x 并发内存模型以及线程支持和原子库。

回答by aib

A static variable usually means multiple invocations of your function would share a state and thus interfere with one another.

静态变量通常意味着您的函数的多次调用将共享一个状态,从而相互干扰。

Normally you want your functions to be self contained; have local copies of everything they work on and share nothing with the outside world bar parameters and return values. (Which, if you think a certain way, aren't a part of the function anyway.)

通常你希望你的函数是自包含的;拥有他们工作的所有内容的本地副本,并且不与外部世界 bar 参数和返回值共享任何内容。(如果您以某种方式思考,无论如何都不是该功能的一部分。)

Consider:

考虑:

int add(int x, int y);

definitely thread-safe, local copies of x and y.

绝对是 x 和 y 的线程安全的本地副本。

void print(const char *text, Printer *printer);

dangerous, someone outside might be doing something with the same printer, e.g. calling another print() on it.

很危险,外面的人可能正在用同一台打印机做某事,例如在它上面调用另一个 print()。

void print(const char *text);

definitely non-thread-safe, two parallel invocations are guaranteed to use the same printer.

绝对非线程安全,保证两个并行调用使用相同的打印机。

Of course, there are ways to secure access to shared resources (search keyword: mutex); this is just how your gut feeling should be.

当然,有一些方法可以保护对共享资源的访问(搜索关键字:)mutex;这就是你的直觉应该是怎样的。

Unsynchronized parallel writes to a variable are also non-thread-safe most of the time, as are a read and write. (search keywords: synchronization, synchronization primitives[of which mutexis but one], also atomicity/atomic operationfor when parallel access is safe.)

大多数情况下,对变量的非同步并行写入也是非线程安全的,读取和写入也是如此。(搜索关键字:synchronizationsynchronization primitives[其中mutex只有一个],还有atomicity/atomic operation用于并行访问是安全的。)