线程Ⅱ
- 🔗接上篇【线程篇Ⅰ】
- 五、线程库 和 线程 id
- 六、同步与互斥
🔗接上篇【线程篇Ⅰ】
👉【Linux】线程篇Ⅰ:线程和task_struct 执行流的理解、相关接口命令、线程异常、线程的私有和共享
五、线程库 和 线程 id
对于 Linux 目前实现的 NPTL 实现而言
pthread_t 类型的线程 ID,本质就是一个 进程地址空间 上的一个地址。
线程篇Ⅰ中涉及到的接口,主要是原生系统库的系统级解决方案,虽然在库中实现但是跟语言一样,比语言更靠近底层罢了。而 C++ 其实是对线程库做的封装!!
虽然原生接口效率更高,但是 语言接口 有跨平台性。不确定只在 Linux 下跑的还是推荐使用语言接口。
另:有如下 线程栈 的理解和应用
- 通过更改 寄存器 ebp、esp 就能 切换 线程栈
- 数据通过
ebp - 偏移量
进行访问或者开辟空间(ebp 是一个相对稳定的位置) - 首地址之所以是低地址,是因为栈的扩展方式 和 ebp 开辟空间的方式(如图)。
/*__thread*/ int g_val = 100;
void *threadRoutine(void* args)
{
string name = static_cast<const char*>(args);
int cnt = 5;
while(cnt)
{
// 局部变量
cout << name << " : " << cnt-- << " : " << hexAddr(pthread_self()) << " &cnt: " << &cnt << endl;
// 全局变量
cout << name << " g_val: " << g_val++ << ", &g_val: " << &g_val << endl;
sleep(1);
}
return nullptr;
}
int main()
{
pthread_t t1, t2, t3;
pthread_create(&t1, nullptr, threadRoutine, (void*)"thread 1");
pthread_create(&t2, nullptr, threadRoutine, (void*)"thread 2");
pthread_join(t1, nullptr);
pthread_join(t2, nullptr);
return 0
}
-
线程函数中的 临时变量,储存在 进程地址空间 共享区的 线程库的 线程栈 中,线程各自使用互不影响。
-
全局变量 储存在主线程的 已初始化数据段,其他新线程访问全局变量访问的是同一个,是并发访问。
-
前面 声明
__thread
(局部存储)字样的全局部变量 ,储存在已初始化数据段,并在产生新线程后,拷贝到 线程库的 线程局部存储段 中,供各自线程使用且互不影响。(由于地址空间的分布规则,全局数据被拷贝后的地址会比原来的地址大很多,如上图示)__thread 定义的全局变量 可以应用在: 带出某一个函数 被 各个线程调用的次数
-
__thread 局部存储 与 static 静态变量 没有关系哦,静态变量被所有线程共享的,存在已初始化数据段。