我们知道进程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. IntrospectorCleanupListener作用

    <!--web.xml--><listener> <listener-class>org.springframework.web.util.Introspector ...

  2. POI2005Bank notes银行货币

    Description Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有n种面值的硬币,面值分别为b1, b2,..., bn. 但是每种硬币有数量限制,现在我 ...

  3. shell获得python的print的值

    #!/usr/bin/env python print('aaa') #!/bin/bash var=`python testpython.py` (注意这个引号,是反引号,Tab上面的那个...) ...

  4. 解决Maven的Could not update project XXX configuration NullPointerException 错误

    1. 从eclipse删除这个项目,但不要从磁盘删除: 2. 关闭eclipse: 3. 删除项目目录下的:.settings目录: 4. 删除项目目录下的:.projects目录: 5. 删除项目目 ...

  5. 在VIM中进行快速的查找和替换

    VIM是被誉为非常高效的文本编辑软件.但是掌握并高效的使用是件有难度的事情.在VIM中进行快速的查找和替换是提高VIM使用效率的重要方法.下面是我在阅读VIM用户手册时整理的一些资料: 行内搜索. f ...

  6. ArcGIS发布服务时缓存切片设置

    [文件]>[共享]>[服务]>[覆盖原有服务]或[创建新服务] 设置好相关参数后,会弹出"服务编辑框": 进入"缓存" 1."绘制此 ...

  7. 搭建IONIC开发环境

    1.准备工作     下载 Node.js(下载包),WebStorm(IDE,编写代码,浏览器调试),JDK(webstorm 运行环境),Android SDK (Android编译)   2.配 ...

  8. 通过form表单获取值

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  9. 三、最小化的Spring XML配置

    Spring 提供了自动装配(自动识别如何装配Bean的依赖关系)和自动检测(检测哪些类需要被配置成Spring Bean) 1.自动装配Bean的属性 1.1四种类型得自动装配:byName.byT ...

  10. jmeter 内存溢出解决方法

    执行“评论新鲜事”200并发就内存溢出 解决方法: [caozijuan@test09 bin]$ vi jmeter JVM_ARGS="-Xms1024m -Xmx4096m" ...