我们知道进程ID是操作系统调度的最小单位,有时候根据业务的需要,我们会使用到多线程技术,当创建了多个线程时,也会有一个线程ID,那这个线程ID和进程ID有什么不一样吗?

其中,线程组的线程ID是属于NPTL(Native POSIX Thread Library)线程库的范畴,属该线程库调度的标识;而调度器的进程ID则属于操作系统的最小调度单位.两者具有在本质上截然不同的意义和使用范围,值得注意!我们来看一个实验代码:线程执行函数thread1和thread2都只做一件事情,输出自己的线程组中的线程ID和被调度器调度的进程ID,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <pthread.h>
#include <sys/syscall.h> /* syscall(SYS_gettid); */ void *thread1();
void *thread2(); int main(int argc, char *argv[])
{
int flag;
pthread_t th1,th2;
flag=pthread_create(&th1,NULL,thread1,NULL);
if(flag != 0)
{
fprintf(stderr,"创建线程1失败[%s]\n",strerror(errno));
exit(0);
} flag=pthread_create(&th2,NULL,thread2,NULL);
if(flag != 0)
{
fprintf(stderr,"创建线程2失败[%s]\n",strerror(errno));
exit(0);
} printf("main进程ID是[%d]\n",getpid()); pthread_join(th1,NULL);
pthread_join(th2,NULL); return 0;
} void *thread1()
{
int tid = syscall(SYS_gettid); /* 被进程调度器调度的进程ID */
printf("这是线程thread1,线程组的线程ID是[%u], 调度器的进程ID = %d\n",(unsigned int)pthread_self(), tid);
/* 让线程不要退出,以便查看在proc下的线程信息 */
pause();
} void *thread2()
{
int tid = syscall(SYS_gettid); /* 被进程调度器调度的进程ID */
printf("这是线程thread2,线程组的线程ID是[%u], 调度器的进程ID = %d\n",(unsigned int)pthread_self(), tid);
/* 让线程不要退出,以便查看在proc下的线程信息 */
pause();
}

运行结果

发现属于NPTL的线程ID的数值非常大(3078654832,3068164976),而属于系统调度器的进程ID则紧跟主进程的进程ID(4180,4181)

在线程没有退出的情况下(使用pause进行模拟),可以使用ls -l /proc/[pid]/task命令查看该进程下的所属线程信息.因为procfs文件系统在task下会给进程的每一个线程都建立一个子目录,目录名称为该线程的被调度的ID.(PS: 使用命令ps -L -p 4179也可以查看)

发现该进程的目录下的确有4180和4181的线程目录.

从本质上来说,属于NPTL范畴的线程ID的类型是pthread_t,而它指向了一个类型为struct pthread的结构体,所以还是一个指针,理解成为一个地址也可以.

而被系统调度的进程ID的类型却是pid_t,它是能被列入到调度队列的.所以,两者还是有很大区别的.

命令ps -L -p 4179的执行结果

./threadid的状态是Sl+,S表示该进程是静止的,l表示是多线程或者克隆线程.

备注:进程或线程的状态列表

D    不可中断     Uninterruptible sleep (usually IO)
    R    正在运行,或在队列中的进程
    S    处于休眠状态
    T    停止或被追踪
    Z    僵尸进程
    W    进入内存交换(从内核2.6开始无效)
    X    死掉的进程

<    高优先级
    N    低优先级
    L    有些页被锁进内存
    s    包含子进程
    +    位于后台的进程组
    l    多线程,克隆线程

线程的2个ID的更多相关文章

  1. 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC…… 依次递归

    import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...

  2. python启动线程查看线程的名称和id;python杀掉进程的方法

    def cpu_app(): print("CPU") #启动一个线程t=threading.Thread(target=cpu_app,args=()) t.daemon = T ...

  3. 第四题(迅雷笔试题):编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

    #include <iostream> #include <stdlib.h> #include <pthread.h> using namespace std; ...

  4. 线程、线程句柄、线程ID

     什么是句柄:句柄是一种指向指针的指针.我们知道,所谓指针是一种内存地址.应用程序启动后,组成这个程序的各对象是住留在内存的.如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址 ...

  5. Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID

    /** * Returns the identifier of this process's user. * 返回此进程的用户的标识符. */ Log.e(TAG, "Process.myU ...

  6. 线程句柄和线程ID的区别

    ●CreateThread() API 用于创建线程. API 返回同时线程句柄,并通过参数得到线程标识符 (ID). 线程句柄有完全访问权创建线程对象. 运行线程时线程 ID 唯一标识线程在系统级别 ...

  7. 【windows 操作系统】线程句柄HANDLE与线程ID的关系

    什么是句柄 句柄是一种指向指针的指针.我们知道,所谓指针是一种内存地址.应用程序启动后,组成这个程序的各对象是住留在内存的.如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访 ...

  8. 查看JAVA进程中哪个线程CPU消耗最高

    一,在centos linux 上查看进程占用cpu过高 top  shift+h 查看哪个进程程消耗最高     二,查看JAVA进程中哪个线程消耗最高   2.1 导出java运行的线程信息   ...

  9. Spring的线程池ThreadPoolTaskExecutor使用案例

    1.Sping配置文件 <!-- 线程池配置 --> <bean id="threadPool" class="org.springframework. ...

随机推荐

  1. 解决NGUI自动被设置LYAER

    解决NGUI自动被设置LYAER uiwidget.cs1011行public void checklayer()这里修改 可以让LAYER不跟随父物体变动 但是这里有个问题 摄像机的CULL 不会被 ...

  2. Oracle ORA-12154: TNS: 无法解析指定的连接标识符”错误

    主要原因: 1.监听服务没有起起来.windows平台个一如下操作:开始---程序---管理工具---服务,打开服务面板,启动oraclehome92TNSlistener服务. 2.database ...

  3. 把本地仓库工程上传到github上和从gitbu同步工程到本地

    1.在本地产生秘钥和公钥 [root@jacky git_project]# ssh-keygen -t rsa -C "jacky-lulu@1073740572@qq.com" ...

  4. h5

    1. 在iPhone 手机上默认值是(电话号码显示为拨号的超链接): <meta name="format-detection" content="telephon ...

  5. CSS3--overflow属性

    overflow:当内容溢出元素框时发生的事情: overflow:默认,内容不会裁剪,会呈现在元素框之外: overflow:hidden:内容会被裁剪,并且其余部分是不可见的(清除浮动) over ...

  6. 移动端设置字体px转换rem的脚本

    (function (){ var _self = this; _self.width = 640;//设置默认最大宽度 _self.fontSize = 100;//默认字体大小 _self.wid ...

  7. php 面试题收集-基础题

    1.表单中 get与post提交方法的区别?答:get是发送请求HTTP协议通过url参数传递进行接收,而post是实体数据,可以通过表单提交大量信息. 2.session与cookie的区别?答:s ...

  8. JavaScipt 事件体系

    事件机制 jQuery对事件的绑定分别有几个API .bind()/.live()/.delegate()/.on() 不管是用什么方式绑定,归根到底还是用addEventListener/attac ...

  9. ThinkPHP 3.2.3(四)架构之多层MVC

    一.模型(Model)层 1.ThinkPHP支持多层Model,不同的模型层都继承自系统的Model类.   2.模型的多层通过目录结构和命名规范区分. 例如:在某个项目设计中需要区分数据层.逻辑层 ...

  10. android事件拦截处理机制详解

    前段时间刚接触过Android手机开发,对它的事件传播机制不是很了解,虽然网上也查了相关的资料,但是总觉得理解模模糊糊,似是而非,于是自己就写个小demo测试了一下.总算搞明白了它的具体机制.写下自己 ...