> 技术文档 > 【Linux】线程ID与互斥、同步(锁、条件变量)_linux 条件锁

【Linux】线程ID与互斥、同步(锁、条件变量)_linux 条件锁

9efbcbc3d25747719da38c01b3fa9b4f.gif

作者主页: 作者主页

本篇博客专栏:Linux

创作时间 :2024年11月24日

9efbcbc3d25747719da38c01b3fa9b4f.gif

线程ID及进程地址空间布局

先看一下这段代码:

运行一下:

运行这个代码之后,我们看到的这个很大的数字就是线程id,然后我们可以用ps -aL命令来查看一下:

这里面的第一串数字就是pid,第二串数字就是LWP,我们可以看到LWP跟线程id是不一样的。所以给用户提供的线程id,不是内核中的lwp,而是pthread库自己维护的一个值

通过这个代码:我们把上面的数字转换成十六进制,可以看出这是一个地址:

理解库

动态库在运行时被加载,动态库没被加载前在磁盘当中

pthread库本质也是一个文件

我们刚刚写的可执行程序,他也是一个文件,他也在磁盘当中,可执行程序内部用线程库来创建多线程。

程序运行的时候,会变成一个进程,加载到内存当中,内存中就有了该进程的代码和数据。创建线程的时候,我们要先把线程库加载到内存当中,然后再映射到该进程的地址空间才能用,映射要映射到堆栈之间的共享区,如果有多个多线程进程,只需要将共享取得代码经过页表映射到已经加载到内存的库,此时多个进程就可以使用同一个库里的方法来创建线程

Linux只维护轻量级进程,linux中的pcb里与执行流相关的属性都是轻量级进程的属性,所有的属性都是围绕lwp展开的。我们在用户层的概念是线程,要的是线程的id,与线程相关的内容在Linux中是没有的,它没有维护。所以这部分属性由库来进行维护。

为了更好的管理线程,创建线程时,库会为我们的每一个线程申请一个内存块(描述线程的相关结构体字段属性)。

未来要找一个线程的所有属性,只要找到线程控制块的地址即可。所以pthread_t id就是一个地址。

pthread_t类型的线程ID,本质就是线程属性集合的起始虚拟地址 ---- 在pthread库中维护。

有这些打印出来的值可以看出,全部变量是受所有线程所控制的

但如果我们这样去写的话:

如果我们想让两个线程各自私有一份变量,g++有一个编译选项 __thread

用__thread修饰这个全局变量即可。运行后,主线程和新线程gval的地址也不一样了。这种情况叫线程的局部存储,原始代码里只看到一个gval,但是他们用的是各自的gval。

这种情况只在Linux中有效。__thread只能用来修饰内置类型