[英]C++: Static variables in multithreaded program
在多线程程序中使用静态变量(特别是在函数内)有什么问题?
谢谢。
初始化不是线程安全的。 两个线程可以进入该函数,并且两个线程都可以初始化函数范围的静态变量。 这不好。 没有人知道结果会是什么。
在C ++ 0x中,函数范围静态变量的初始化将是线程安全的; 调用该函数的第一个线程将初始化该变量,并且调用该函数的任何其他线程将需要阻塞,直到该初始化完成。
我认为目前没有任何编译器+标准库对完全实现C ++ 0x并发内存模型以及线程支持和原子库。
要随机选择一个说明性示例,请在C库中使用类似asctime
的界面。 原型看起来像这样:
char *
asctime(const struct tm *timeptr);
这隐式必须有一些全局缓冲区来存储返回的char*
中的char*
。 实现这一目标的最常见和最简单的方法是:
char *
asctime(const struct tm *timeptr)
{
static char buf[MAX_SIZE];
/* TODO: convert timeptr into string */
return buf;
}
这在多线程环境中完全被破坏,因为对于每次调用asctime()
, buf
将位于相同的地址。 如果两个线程同时调用asctime()
,则它们可能会覆盖彼此的结果。 在asctime()
的契约中隐含的是字符串的字符将一直存在,直到下一次调用asctime()
,并发调用会打破它。
在这个特定的例子中,有一些语言扩展通过线程局部存储( __thread
, __declspec(thread)
)来解决这个特定问题。 我相信这个想法使它成为C ++ 0x作为thread_local
关键字。
即便如此,我认为以这种方式使用它是一个糟糕的设计决策,原因类似于使用全局变量的原因。 除此之外,它可以被认为是调用者维护和提供这种状态而不是被调用者的更清晰的接口。 然而,这些是主观论点。
静态变量通常意味着您的函数的多次调用将共享一个状态,从而相互干扰。
通常你希望你的功能是自包含的; 拥有他们工作的所有内容的本地副本,并与外部世界条形参数和返回值无任何共享。 (如果你认为某种方式,那么无论如何都不是这个功能的一部分。)
考虑:
int add(int x, int y);
绝对是线程安全的x和y的本地副本。
void print(const char *text, Printer *printer);
危险,外面的人可能正在使用同一台打印机做某事,例如在其上调用另一个print()。
void print(const char *text);
绝对是非线程安全的,两个并行调用保证使用相同的打印机。
当然,有一些方法可以保护对共享资源的访问(搜索关键字: mutex
); 这就是你的直觉。
对变量的非同步并行写入在大多数情况下也是非线程安全的,读写也是如此。 (搜索关键词: synchronization
, synchronization primitives
[其中mutex
的只有一个],以及并行访问安全时的atomicity
/ atomic operation
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.