在一个进程中定义的全局或静态变量都是所有线程可见的,即每个线程共同操作一块存储区域。而有时我们可能有这样的需求:对于一个全局变量,每个线程对其的修改只在本线程内有效,各线程之间互不干扰。即每个线程虽然共享这个全局变量的名字,但这个变量的值就像只有在本线程内才会被修改和读取一样。
线程局部存储和线程特有数据都可以实现上述需求。
1. 线程局部存储
线程局部存储提供了持久的每线程存储,每个线程都拥有一份对变量的拷贝。线程局部存储中的变量将一直存在,直到线程终止,届时会自动释放这一存储。一个典型的例子就是errno的定义(uClibc-0.9.32),每个线程都有自己的一份errno的拷贝,防止了一个线程获取errno时被其他线程干扰。
要定义一个线程局部变量很简单,只需简单的在全局或静态变量的声明中包含__thread说明符即可。例如:
static __thread int buf[MAX_ERROR_LEN];
这样定义的变量,在一个线程中只能看到本线程对其的修改。
关于线程局部变量的声明和使用,需要注意以下几点:
1. 如果变量声明中使用了关键字static或extern,那么关键字__thread必须紧随其后。
2. 与一般的全局或静态变量声明一样,线程局部变量在声明时可以设置一个初始值。
3. 可以使用C语言取址操作符(&)来获取线程局部变量的地址。
在一个线程中修改另一个线程的局部变量:
__thread变量并不是在线程之间完全隐藏的,每个线程保存自己的一份拷贝,因此每个线程的这个变量的地址不同。但这个地址是整个进程可见的,因此一个线程获得另外一个线程的局部变量的地址,就可以修改另一个线程的这个局部变量。
C++中对__thread变量的使用有额外的限制:
1. 在C++中,如果要在定义一个thread-local变量的时候做初始化,初始化的值必须是一个常量表达式。
2. __thread只能修饰POD类型,即不带自定义的构造、拷贝、赋值、析构的类型,不能有non-static的pr