线程基本操作 (6)线程安全
线程安全 (thread-safe)
单个线程的程序就是一条支流很简单的单步运行.
多线程的程序,就会产生多条分支,并行执行.
那么并行中,有时候不能相互干扰,有时候需要进行相互通信.
(要确保,不相互干扰的时候,他们之间的数据不公用. 相互通信的时候,能够保证数据的同步)

不相互干扰:
创建的每个线程都有自己的栈地址空间,每个线程中的局部变量都是定义在线程栈中的(和函数有点类似).每个线程栈都是独立的,不会相互干扰.
有一个问题,假设我定义了3个新的线程A,B,C.
三个新线程调用了同一个初始start函数(每个线程运行时候,都调用同一个函数),这个函数中有局部变量的定义,那么,每个线程在调用函数的时候,都会定义局部变量到自己的栈中.

可重入函数:
(重入指的是,同一个函数被不同线程调用,前一个线程还没有跳出该函数,另一个线程又开始调用该函数了.)

可重入函数特点:
1,函数内操作的变量都是内部定义的局部变量.这些变量是在栈空间中的.当函数调用结束返回时,再由系统回收所占用的栈.局部变量的声明周期只限于函数执行期间.
2,函数的形参和返回值都是值类型,而不是引用类型(指针).
3,函数中调用的其他子函数,也是可重入的.
4,如果函数内部有全局变量,且全局变量仅仅限于读取,这样也可认为是可重入.
在man手册中,经常看到一些函数有两个版本,
一种是带_r后缀的,一种没有带后缀.
那么带后缀_r的意思,就是可重入版本了.


一次性初始化
(函数中,有一部分代码只需要进行一次执行,比如:初始化代码)
如果多个线程都要执行 init_routine(),
那么只能有一个函数会真真的执行 init_routine() 其他函数都会进入阻塞状态.
// 例子:
编译并运行:


线程特有数据
线程特有数据,也称为线程私有数据,
就是为每个调用线程分别维护一份变量的副本(copy).
每个线程通过特有数据键(key)访问时,
这个特有数据键就会获得本线程绑定的变量副本.
这样就可以避免成为多个线程间的共享数据.
c库中,有很多函数都是非线程安全函数.
线程特有数据的思想就为每一个调用线程,分配属于线程的私有数据区,
为每个线程分别维护一份变量的副本.
涉及到3个函数:

线程局部存储
通常情况下,进程中定义的全局变量是被其下所有线程共享的.
所有线程都可以访问这些全局变量.
线程局部存储和线程特有数据实现的功能基本类似.
都是让各个线程拥有一份对变量的拷贝.
线程局部存储的优点是使用简单.(相比线程特有数据要简单).
线程局部存储:
关键字 __thread, 在变量前加上__thread
线程局部存储关键字是 __thread.
如果与static或extern连用,需要把 __thread 放到其后.
线程局部存储的变量,可以在定义的时候赋初始值.
可以用&来获取线程局部变量的地址.
线程局部存储需要内核,pthreads,gcc编译器的支持.