简体   繁体   English

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

[英]C++: Static variables in multithreaded program

What is the problem with having static variables (especially within functions) in multithreaded programs? 在多线程程序中使用静态变量(特别是在函数内)有什么问题?

Thanks. 谢谢。

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; 在C ++ 0x中,函数范围静态变量的初始化将是线程安全的; 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. 调用该函数的第一个线程将初始化该变量,并且调用该函数的任何其他线程将需要阻塞,直到该初始化完成。

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并发内存模型以及线程支持和原子库。

To pick an illustrative example at random, take an interface like asctime in the C library. 要随机选择一个说明性示例,请在C库中使用类似asctime的界面。 The prototype looks like this: 原型看起来像这样:

 char *
 asctime(const struct tm *timeptr);

This implicitly must have some global buffer to store the characters in the char* returned. 这隐式必须有一些全局缓冲区来存储返回的char*中的char* The most common and simple way to accomplish this would be something like: 实现这一目标的最常见和最简单的方法是:

 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 buf will be at the same address for each call to asctime() . 这在多线程环境中完全被破坏,因为对于每次调用asctime()buf将位于相同的地址。 If two threads call asctime() at the same time, they run the risk of overwriting each other's results. 如果两个线程同时调用asctime() ,则它们可能会覆盖彼此的结果。 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. asctime()的契约中隐含的是字符串的字符将一直存在,直到下一次调用asctime() ,并发调用会打破它。

There are some language extensions that work around this particular problem in this particular example via thread-local storage ( __thread , __declspec(thread) ). 在这个特定的例子中,有一些语言扩展通过线程局部存储( __thread__declspec(thread) )来解决这个特定问题。 I believe this idea made it into C++0x as the thread_local keyword. 我相信这个想法使它成为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. 然而,这些是主观论点。

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.) (如果你认为某种方式,那么无论如何都不是这个功能的一部分。)

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, eg 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 ); 当然,有一些方法可以保护对共享资源的访问(搜索关键字: mutex ); this is just how your gut feeling should be. 这就是你的直觉。

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 mutex is but one], also atomicity / atomic operation for when parallel access is safe.) (搜索关键词: synchronizationsynchronization primitives [其中mutex的只有一个],以及并行访问安全时的atomicity / atomic operation 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM