1、问题复现
1.1 执行docker-compose报错
docker-compose logs -f jdk8
runtime: failed to create new OS thread (have 3 already; errno=12)
fatal error: newosproc
runtime stack:
runtime.throw({0x1f65c1c?, 0x7ffc37e00af0?})
runtime/panic.go:1047 +0x5d fp=0x7ffc37e00ac8 sp=0x7ffc37e00a98 pc=0x43811d
runtime.newosproc(0xc00009a400)
runtime/os_linux.go:195 +0x176 fp=0x7ffc37e00b30 sp=0x7ffc37e00ac8 pc=0x4345d6
runtime.newm1(0xc00009a400)
runtime/proc.go:2253 +0xcf fp=0x7ffc37e00b70 sp=0x7ffc37e00b30 pc=0x43ea4f
runtime.newm(0x745c91f94079f5?, 0xc00006a500, 0x2b97428?)
runtime/proc.go:2228 +0x12c fp=0x7ffc37e00ba0 sp=0x7ffc37e00b70 pc=0x43e90c
runtime.startm(0xc00006a500, 0x1)
runtime/proc.go:2411 +0xf3 fp=0x7ffc37e00bf0 sp=0x7ffc37e00ba0 pc=0x43eeb3
runtime.wakep()
runtime/proc.go:2541 +0xf6 fp=0x7ffc37e00c20 sp=0x7ffc37e00bf0 pc=0x43f496
runtime.newproc.func1()
runtime/proc.go:4251 +0x53 fp=0x7ffc37e00c48 sp=0x7ffc37e00c20 pc=0x4433d3
runtime.systemstack()
runtime/asm_amd64.s:496 +0x49 fp=0x7ffc37e00c50 sp=0x7ffc37e00c48 pc=0x469d49
1.2 执行docker info报错
docker info
runtime/cgo: pthread_create failed: Resource temporarily unavailable
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7f28ec617387 m=0 sigcode=18446744073709551610
1.3 执行系统提示报错
1.4 java服务报错
java.lang.OutOfMemoryError: unable to create new native thread
2、问题定位
-
查看系统当前【线程/进程】总数
[root@localhost ~]# ps -eLf | wc -l 32065 [root@localhost ~]# pstree -p | wc -l 32040
-
查看系统进程数限制
[root@localhost ~]# sysctl kernel.pid_max kernel.pid_max = 32768 [root@localhost ~]# cat /etc/sysctl.conf | grep pid kernel.core_uses_pid = 1 kernel.pid_max = 32768 [root@localhost ~]# cat /proc/sys/kernel/pid_max 32768
-
查看当前线程数占用前5的进程信息
[root@localhost ~]# ps -eo pid,ppid,nlwp,cmd --sort=-nlwp | head -n 5 PID PPID NLWP CMD 27547 27395 7115 java -jar xxx.jar 27562 27416 6894 java -jar xxx.jar 27548 27394 6846 java -jar xxx.jar 45213 45189 345 java -jar xxx.jar
-
使用 ps -L 查看具体进行的线程使用情况
[root@VM-0-44-centos translation]# ps -L -p 45213 PID LWP TTY TIME CMD 45213 45213 ? 00:00:00 java 45213 45290 ? 00:00:06 java 45213 45291 ? 00:00:03 java 45213 45292 ? 00:00:03 java 45213 45293 ? 00:00:03 java 45213 45294 ? 00:00:03 java 45213 45295 ? 00:00:03 java 45213 45296 ? 00:00:03 java 45213 45297 ? 00:00:03 java 45213 45298 ? 00:00:03 java 45213 45299 ? 00:00:03 java 45213 45300 ? 00:00:03 java 45213 45301 ? 00:00:03 java 45213 45302 ? 00:00:03 java 45213 45303 ? 00:00:03 java 45213 45304 ? 00:00:12 VM Thread 45213 45305 ? 00:00:00 Reference Handl 45213 45306 ? 00:00:00 Finalizer 45213 45307 ? 00:00:00 Signal Dispatch 45213 45308 ? 00:00:21 C2 CompilerThre 45213 45309 ? 00:00:19 C2 CompilerThre
3、问题原因
根据上述步骤得知,是系统的线程资源达到了上限,但是线程资源为什么会占用pid资源呢,下面的deepseek的回答:
-
Linux 线程的本质:Linux 通过 轻量级进程(LWP, Light Weight Process) 实现线程,线程与进程共享相同的底层机制:
- 线程是共享地址空间的进程:每个线程拥有独立的 task_struct(内核中的进程描述符),但与其他线程共享内存、文件描述符等资源。
- 线程占用独立的 PID 和 LWP ID:
- PID(进程ID):所有线程共享主进程的 PID。
- LWP(线程ID):每个线程有一个独立的 LWP ID(在用户态显示为 TID,可通过 gettid() 获取),内核视其为独立的调度单元。
-
线程如何占用 PID 资源?
- 每个线程消耗一个内核 PID 槽位:
虽然用户态看到的线程属于同一个进程(共享 PID),但在内核中,每个线程会占用一个独立的 PID 编号(通过 ps -eLf 的 LWP 列可见)。- 例如:一个进程有 100 个线程 → 内核需要分配 100 个 PID 槽位(即使 ps -ef 只显示 1 个 PID)。
- 受系统级 pid_max 限制:
线程数受 /proc/sys/kernel/pid_max 限制(默认通常为 32768 或更高)。- 如果系统有 1000 个进程,每个进程创建 100 个线程 → 需要 100,000 个 PID 槽位,可能触发 fork: Cannot allocate memory 错误。
- 每个线程消耗一个内核 PID 槽位:
4、问题解决
在 Linux 中,kernel.pid_max 参数决定了系统允许的最大进程/线程数,所以修改上限值可以解决上述问题:
-
临时设置 kernel.pid_max,但重启后失效
sysctl -w kernel.pid_max=65535
-
永久设置 kernel.pid_max
vim /etc/sysctl.conf
在文件末尾添加:
kernel.pid_max = 65535
应用配置
sysctl -p