背景
pthread 库中有一个 pthread_self() 接口用来获取线程 ID,但是这个 ID并不是内核中那个线程 ID,pthread_t 到底是个什么样的数据结构呢?因为 POSIX 标准并没有限制 pthread_t 的数据类型,所以该类型取决于具体实现。对于 Linux 目前使用的 NPTL 实现而言,pthread_t 类型的线程 ID,本质上就是一个进程地址空间上的一个地址,而且 pthread_t 类型的线程 ID很有可能被复用。进程之间不会存在重复的线程 ID,而且不同线程之间也不会重复,在任意时刻都是全局唯一的值。
来源:在学习偏向锁的过程中,偏向锁是不能重新偏向的,为什么在各个线程中发现都是偏向到同一个线程?
上一个线程拿到锁之后,是偏向锁。现在一个新线程拿到锁之后,可能复用了上一个ID。JVM判断加锁的对象是可偏向的,进一步对比发现偏向的线程还是当前线程,所以偏向锁使用成功。实际上这是一个新线程了。其实这样加上偏向锁性能还好些,免得升级锁。
证明
JNI native code 获取线程ID
1 2 3 4 5
| JNIEXPORT void JNICALL Java_jnitool_JniTool_getThreadID (JNIEnv * env, jobject obj){ fprintf(stdout,"java_lock log PID = %d TID = %lu \n",getpid(),pthread_self());
}
|
测试代码,让线程顺序执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public static void main(String[] args) throws Exception {
out.println("\n main ------------------------ start"); JniTool jniTool = new JniTool(); Thread thread1 = new Thread(new Runnable() { public void run() { out.println("t1------------------------ start"); jniTool.getThreadID(); out.println("java getId "+(Thread.currentThread().getId())); out.println("t1------------------------ end"); } });
thread1.start(); thread1.join();
Thread thread2 = new Thread(new Runnable() { public void run() { out.println("t2------------------------start"); jniTool.getThreadID(); out.println("java getId "+(Thread.currentThread().getId())); out.println("t2------------------------end"); } });
thread2.start(); thread2.join();
Thread thread3 = new Thread(new Runnable() { public void run() { out.println("t3------------------------start"); jniTool.getThreadID(); out.println("java getId "+(Thread.currentThread().getId())); out.println("t3------------------------end"); } });
thread3.start(); thread3.join(); out.println("\n main ------------------------ end"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| main ------------------------ start t1------------------------ start java_lock log PID = 55 TID = 140073151424256 java getId 8 t1------------------------ end t2------------------------start java_lock log PID = 55 TID = 140073151424256 java getId 9 t2------------------------end t3------------------------start java_lock log PID = 55 TID = 140073151424256 java getId 10 t3------------------------end
main ------------------------ end
|
观察输出,查看线程ID 确实被复用了。