在C中,在全局范围内声明变量static使其成为全局变量。这个全局变量是在线程之间共享还是按线程分配?
更新: 如果它们是在线程之间共享的,那么在预先存在的库中使用独特的线程/非共享的全局变量是一种简单的方法吗?
UPDATE2: 基本上,我需要以线程安全的方式使用带有全局变量的预先存在的C库。
答案 0 :(得分:16)
整个过程都可以看到,即所有线程。当然,这是在实践中。从理论上讲,你不能说因为线程与C标准无关(至少达到c99,这是提出这个问题时生效的标准)。
但是我用过的所有线程库都会有所有线程都可以访问的全局变量。
更新1:
许多线程库(pthreads,for one)将允许您创建特定于线程的数据,这是一种用于创建和使用特定于线程的数据的函数的方法,而无需通过该函数向下传递。
因此,例如,返回伪随机数的函数可能希望每个线程都有一个独立的种子。因此,每次调用它时,都会创建或附加到保存该种子的线程特定块(使用某种键)。
这允许函数保持与非线程函数相同的签名(例如,如果它们是ISO C函数,则很重要),因为另一个解决方案涉及向函数调用本身添加特定于线程的指针。
另一种可能性是拥有一个全局变量数组,每个线程得到一个,例如:
int fDone[10];
int idx;
: : :
for (i = 0; i < 10; i++) {
idx = i;
startThread (function, i);
while (idx >= 0)
yield();
}
void function () {
int myIdx = idx;
idx = -1;
while (1) {
: : :
}
}
这将允许线程函数被告知数组中的哪个全局变量属于它。
毫无疑问,还有其他方法,但不了解目标环境,讨论它们没有多大意义。
更新2:
在线程环境中使用非线程安全库的最简单方法是使用互斥保护提供包装调用。
例如,假设您的库具有非线程安全的doThis()
函数。你做的是为它提供一个包装器:
void myDoThis (a, b) {
static mutex_t serialize;
mutex_claim (&serialize);
doThis (a, b);
mutex_release (&serialize);
}
将会发生的情况是,一次只有一个线程能够声明互斥锁(因此调用非线程安全函数)。其他人将被阻止,直到当前的人返回。
答案 1 :(得分:1)
C / C ++标准不支持线程。所以线程之间共享所有变量。 在C / C ++运行时库中实现的线程支持,它不是标准的一部分。运行时特定于C / C ++的每个实现。如果您想用C ++编写可移植代码,可以使用boost interprocess library。
要在Microsoft Visual Studio中声明线程局部变量,您可以使用Microsoft特定关键字__declspec( thread )
。
答案 2 :(得分:1)
正如@Pax所提到的,静态变量对所有线程都是可见的。没有与特定线程关联的C ++数据结构。
但是,在Windows上,您可以使用TlsAlloc API为特定于线程的数据分配索引,并将该索引放在静态变量中。每个线程都有自己的插槽,您可以使用此索引以及TlsGetValue和TlsSetValue进行访问。有关详细信息,请参阅MSDN上的Using Thread Local Storage。
更新:没有办法让预先存在的库中的全局变量是特定于线程的。任何解决方案都需要您修改代码,以便知道数据具有线程关联性。