- 浏览: 159624 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
西巴拉古呀那:
Linux多线程并发服务器编程(线程池,FTP服务器)网盘地址 ...
多线程服务器的适用场合 -
somefuture:
第四题怎麼用位图法。写了半天没出来,用了下面的,速度很快pri ...
位图法应用 -
寂寞秋江:
系统,全面,条理清晰,由浅入深,简直是集大成之作。 特别是最后 ...
单个进程最大线程数 -
darkjune:
有点意思, 不错
单个进程最大线程数 -
kidding87:
谢谢啦,收藏着
google使用一点敲门分享
原文链接:http://jzhihui.iteye.com/blog/1271122
windows 操作系统中允许的最大线程数。
===========================================================================
默认情况下,一个线程的栈要预留1M的内存空间
而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程
但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小。
你也可以通过连接时修改默认栈大小,将其改的比较小,这样就可以多开一些线程。
如将默认栈的大小改成512K,这样理论上最多就可以开4096个线程。
即使物理内存再大,一个进程中可以起的线程总要受到2GB这个内存空间的限制。
比方说你的机器装了64GB物理内存,但每个进程的内存空间还是4GB,其中用户态可用的还是2GB。
如果是同一台机器内的话,能起多少线程也是受内存限制的。每个线程对象都要站用非页面内存,而
非页面内存也是有限的,当非页面内存被耗尽时,也就无法创建线程了。
如果物理内存非常大,同一台机器内可以跑的线程数目的限制值会越来越大。
在Windows下写个程序,一个进程Fork出2000个左右线程就会异常退出了,为什么?
这个问题的产生是因为windows32位系统,一个进程所能使用的最大虚拟内存为2G,而一个线程的
默认线程栈StackSize为1024K(1M),这样当线程数量逼近2000时,2000*1024K=2G(大约),
内存资源就相当于耗尽。
MSDN原文:
“The number of threads a process can create is limited by the available virtual memory.
By default, every thread has one megabyte of stack space. Therefore, you can create
at most 2,028 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per
processor and build queues of requests for which the application maintains the context
information. A thread would process all requests in a queue before processing requests
in the next queue.”
如何突破2000个限制?
可以通过修改CreateThread参数来缩小线程栈StackSize,例如
- #define MAX_THREADS 50000
- DWORD WINAPI ThreadProc( LPVOID lpParam ){
- while(1){
- Sleep(100000);
- }
- return 0;
- }
- int main() {
- DWORD dwThreadId[MAX_THREADS];
- HANDLE hThread[MAX_THREADS];
- for(int i = 0; i < MAX_THREADS; ++i){
- hThread[i] = CreateThread(0, 64, ThreadProc, 0, STACK_SIZE_PARAM_IS_A_RESERVATION, &dwThreadId[i]);
- if(0 == hThread[i]){
- DWORD e = GetLastError();
- printf(“%d\r\n”,e);
- break;
- }
- }
- ThreadProc(0);
- }
服务器端程序设计
如果你的服务器端程序设计成:来一个client连接请求则创建一个线程,那么就会存在2000个限制(在
硬件内存和CPU个数一定的情况下)。建议如下:
The “one thread per client” model is well-known not to scale beyond a dozen clients
or so. If you‘re going to be handling more than that many clients simultaneously,
you should move to a model where instead of dedicating a thread to a client, you
instead allocate an object. (Someday I’ll muse on the duality between threads and
objects.) Windows provides I/O completion ports and a thread pool to help you
convert from a thread-based model to a work-item-based model.
1. Serve many clients with each thread, and use nonblocking I/O and level-triggered
readiness notification
2. Serve many clients with each thread, and use nonblocking I/O and readiness
change notification
3. Serve many clients with each server thread, and use asynchronous I/O
--------------------
附:Win32将低区的2GB留给进程使用, 高区的2GB则留给系统使用。
Linux将高位1GB留给内核,低位3GB留给进程
linux系统中允许的最大线程数
==========================================================================================
JVM中可生成的最大Thread数量
JVM中可以生成的最大数量由JVM的堆内存大小、Thread的Stack内存大小、系统最大
可创建的线程数量(Java线程的实现是基于底层系统的线程机制来实现的,Windows下_beginthreadex,Linux下pthread_create)三个方面影响。
-Xms |
intial java heap size |
-Xmx |
maximum java heap size |
-Xss |
the stack size for each thread |
系统限制 |
系统最大可开线程数 |
- import java.util.concurrent.atomic.AtomicInteger;
- public class TestThread extends Thread {
- private static final AtomicInteger count = new AtomicInteger();
- public static void main(String[] args) {
- while (true)
- (new TestThread()).start();
- }
- @Override
- public void run() {
- System.out.println(count.incrementAndGet());
- while (true)
- try {
- Thread.sleep(Integer.MAX_VALUE);
- } catch (InterruptedException e) {
- break;
- }
- }
- }
测试环境:
系统:Ubuntu 10.04 Linux Kernel 2.6 (32位)
内存:2G
JDK:1.7
测试结果:
◆ 不考虑系统限制
-Xms |
-Xmx |
-Xss |
结果 |
1024m |
1024m |
1024k |
1737 |
1024m |
1024m |
64k |
26077 |
512m |
512m |
64k |
31842 |
256m |
256m |
64k |
31842 |
在创建的线程数量达到31842个时,系统中无法创建任何线程。
由上面的测试结果可以看出增大堆内存(-Xms,-Xmx)会减少可创建的线程数量,增大线程栈内存
(-Xss,32位系统中此参数值最小为60K)也会减少可创建的线程数量。
◆ 结合系统限制
线程数量31842的限制是是由系统可以生成的最大线程数量决定的:/proc/sys/kernel/threads-max,
可其默认值是32080。修改其值为10000:echo 10000 > /proc/sys/kernel/threads-max,
修改后的测试结果如下:
-Xms |
-Xmx |
-Xss |
结果 |
256m |
256m |
64k |
9761 |
这样的话,是不是意味着可以配置尽量多的线程?再做修改:echo 1000000 > /proc/sys/kernel/threads-max,
修改后的测试结果如下:
-Xms |
-Xmx |
-Xss |
结果 |
256m |
256m |
64k |
32279 |
128m |
128m |
64k |
32279 |
发现线程数量在达到32279以后,不再增长。查了一下,32位Linux系统可创建的最大pid数是32678,
这个数值可以通过/proc/sys/kernel/pid_max来做修改(修改方法同threads-max),但是在32系
统下这个值只能改小,无法更大。在threads-max一定的情况下,修改pid_max对应的测试结果如下:
pid_max |
-Xms |
-Xmx |
-Xss |
结果 |
1000 |
128m |
128m |
64k |
582 |
10000 |
128m |
128m |
64k |
9507 |
在Windows上的情况应该类似,不过相比Linux,Windows上可创建的线程数量可能更少。基于线
总结:
JVM中可以生成的最大数量由JVM的堆内存大小、Thread的Stack内存大小、系统最大可创建的线程数量
(Java线程的实现是基于底层系统的线程机制来实现的,Windows下_beginthreadex,Linux下
pthread_create)三个方面影响。具体数量可以根据Java进程可以访问的最大内存(32位系统上一般2G)、
堆内存、Thread的Stack内存来估算。
序:
在64位Linux系统(CentOS 6, 3G内存)下测试,发现还有一个参数是会限制线程数量:
max user process(可通过ulimit –a查看,默认值1024,通过ulimit –u可以修改此值),
这个值在上面的32位Ubuntu测试环境下并无限制。
将threads-max,pid_max,max user process,这三个参数值都修改成100000,-Xms,
-Xmx尽量小(128m,64m),-Xss尽量小(64位下最小104k,可取值128k)。事先预测在
这样的测试环境下,线程数量就只会受限于测试环境的内存大小(3G),可是实际的测试结果是
线程数量在达到32K(32768,创建的数量最多的时候大概是33000左右)左右时JVM是抛出警告:
Attempt to allocate stack guard pages failed,然后出现OutOfMemoryError无法创建本
地线程。查看内存后发现还有很多空闲,所以应该不是内存容量的原因。Google此警告无果,
暂时不知什么原因,有待进一步研究。
序2:今天无意中发现文章[7],马上试了下,果然这个因素会影响线程创建数量,按文中描述把/proc/sys/vm/max_map_count的数量翻倍,从65536变为131072,创建的线程总数
量达到65000+,电脑基本要卡死(3G内存)… 简单查了下这个参数的作用,在[8]中的描述如下:
“This file contains the maximum number of memory map areas a process may have.
Memory map areas are used as a side-effect of calling malloc, directly by mmap and
mprotect, and also when loading shared libraries.
While most applications need less than a thousand maps, certain programs,
particularly malloc debuggers, may consume lots of them, e.g., up to one or two
maps per allocation.
The default value is 65536.”
OK,这个问题总算完满解决,最后总结下影响Java线程数量的因素:
Java虚拟机本身:-Xms,-Xmx,-Xss;
系统限制:
/proc/sys/kernel/pid_max,
/proc/sys/kernel/thread-max,
max_user_process(ulimit -u),
/proc/sys/vm/max_map_count。
参考资料:
1. http://blog.krecan.net/2010/04/07/how-many-threads-a-jvm-can-handle/
2. http://www.cyberciti.biz/tips/maximum-number-of-processes-linux-26-kernel-can-handle.html
3. http://geekomatic.ch/2010/11/24/1290630420000.html
4. http://stackoverflow.com/questions/763579/how-many-threads-can-a-java-vm-support
5. http://www.iteye.com/topic/1035818
6. http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html
7. https://listman.redhat.com/archives/phil-list/2003-August/msg00025.html
8. http://www.linuxinsight.com/proc_sys_vm_max_map_count.html
评论
特别是最后一点,/proc/sys/vm/max_map_count ,这个配置项,以前还没听说过,有收获,多谢多谢。
发表评论
-
阻塞同步 lock
2013-05-03 08:39 931转自:http://blog.csdn.net/chen7 ... -
阻塞同步synchronized
2013-05-03 08:40 1273转自:http://blog.csdn.net/chen7 ... -
关于中断处理
2013-05-03 08:41 884在历史上,Java试图提供过抢占式限制中断,但问题多多,例如前 ... -
wait和notify机制
2014-03-03 13:47 1034Wait-Notify机制可以说是实现阻塞操作较为高效的一 ... -
lock和lockInterruptibly
2014-03-03 13:47 5268lockInterruptibly()允许在等待时由其他线程 ... -
流io 读
2014-03-03 13:47 6731. 关于InputStream.read() ... -
设计模式之不变模式(Immutable Pattern)分析
2014-03-06 10:55 843主要介绍编写不变类的主意事项: 归纳一下设计不变类的 5 ... -
jvm参数
2014-03-03 13:47 629作者:Ken Wu Email: ken.wu ... -
Java Object Initialization Order - Know your JLS!
2012-10-20 21:41 920转自:http://www.danielschneller.c ... -
jvm参数配置
2014-03-03 13:48 592/usr/local/jdk/bin/java -D ... -
读取Properties文件的六种方法
2014-03-14 10:11 7261。使用java.util.Properties类的load ... -
从Java视角理解伪共享(False Sharing)
2014-03-14 10:11 739从Java视角理解系统结构 ... -
从Java视角理解CPU缓存(CPU Cache)
2014-03-14 10:11 1191从Java视角理解系统结构 ... -
从Java视角理解CPU上下文切换(Context Switch)
2014-03-16 10:52 1719从Java视角理解系统结 ... -
浅谈JAVA ThreadPoolExecutor
2014-03-12 09:37 931基础 在我看来,java比C++的一个大好处就是提供了对 ... -
Java多线程同步如何从JVM的角度体会
2014-03-18 20:20 793我们在使用Java多线程 ... -
java 安全沙箱模型
2012-02-22 21:15 819起到第一道安全保障作 ... -
jvm的线程创建
2012-01-09 13:48 4034在操作系统中,有两种不同的方法提供线程支持:用户层的用户线程, ... -
简单的路径使用(转)
2011-12-03 11:38 744用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还 ...
相关推荐
### 进程与线程的生动形象理解 #### 一、引言 进程与线程作为操作系统中的核心概念,对于理解和开发高效的软件至关重要。本文旨在通过一个生动的类比来帮助读者更好地理解进程与线程的基本概念及其差异,并进一步...
在多任务或多线程环境下,了解CPU支持的最大线程数至关重要,因为它直接影响到系统能够并发处理的工作量。"获取本机CPU支持的最大线程数"这个工具正是为了帮助用户快速、方便地获取这一信息。 首先,我们要理解什么...
这意味着单个进程可以同时处理多个请求,提高了并发能力。在配置上,Worker MPM 有一些与 prefork 类似的参数,但也有一些特有的配置项,例如: - `ThreadsPerChild`:每个子进程中的线程数量。 - `MaxClients`:...
而跨进程通信则可以解决单个进程资源限制的问题。 在提供的压缩包文件中,"www.pudn.com.txt"可能包含了关于这个主题的进一步资料,而"创建进程"可能是示例代码或者详细教程。通过阅读这些文件,你可以更深入地学习...
- **线程**:同一进程中的多个线程可以在单个处理器上并发执行,也可以在多核处理器上实现并行。 #### 四、线程间的同步机制 1. **互斥锁(Mutex)**: - 互斥锁是一种简单的同步机制,用于保护对共享资源的访问...
【进程与线程解释】 进程和线程是操作系统中至关重要的概念,它们是计算机系统并发执行任务的基础。这里,我们通过一个生动的工厂车间比喻来理解这两个概念。 1. **CPU与工厂** - CPU(中央处理器)是计算机的...
在单个程序中同时运行多个线程来完成不同的工作,即多线程编程。多线程编程允许线程之间共享数据,实现并行处理,提高程序的执行效率和响应速度,尤其是在执行I/O操作时。程序在CPU和内存使用上更加高效,还可以利用...
在本例中,多线程可能被用于服务端或客户端,以便在单个进程中同时处理多个任务,如接收和响应客户端请求。 3. **时间服务**:服务端向客户端发送系统时间的功能,通常涉及网络编程,如套接字(socket)编程。...
从用户和操作系统的角度来看,每个进程似乎都有一个独立的虚拟CPU在为其服务,但实际上,在单个物理CPU的情况下,这些进程是在时间片的基础上轮换执行的。 在图2-1中,我们可以看到在一台多道程序计算机中,内存被...
而多线程则是在单个进程中创建多个执行线程,这些线程共享同一内存空间,可以并发执行任务,提高程序执行效率。 文件映射(Memory-Mapped Files)是Windows系统提供的一种高效的数据共享机制,它允许将文件直接映射...
多线程可以在单个进程中并发执行,提高程序的执行效率。 【实验目的】 实验旨在让学生深入理解进程和线程的概念以及它们在操作系统中的实现。通过实际操作,学生将学习如何创建和管理进程,以及进程间通信的方式。...
- 在单个进程中可以有多个线程,它们共享相同的内存空间,但每个线程有自己的程序计数器、栈和局部变量。 - 线程间的切换开销比进程小,因为它们共享大部分资源,使得多线程在处理并发任务时效率更高。 - 线程又...
1. **资源利用率**:多线程可以在单个进程中并发执行,充分利用CPU时间,提高系统的执行效率。 2. **并发执行**:线程间切换比进程间切换更快,因为它们共享同一内存空间,减少了上下文切换的开销。 3. **任务分解...
对于需要高并发且资源限制不是非常严格的环境,可以选择按线程方式运行虚拟用户以最大化资源利用率;而对于资源敏感或者需要更加稳定的测试环境,则应考虑采用按进程方式运行虚拟用户。理解并合理利用这两种模式可以...
- `ProcessThread.CpuUsage`属性可以获取单个线程的CPU使用率。 5. **源代码结构**: - `Example.cs`可能包含使用这些方法的示例代码。 - `ProcessCpu.cs`和`ThreadCpu.cs`可能是专门处理进程和线程CPU利用率的...
在Linux系统中,进程和线程是两种不同的执行单元,它们是系统管理和调度...例如,通过创建子进程处理不同的任务,或在单个进程中使用线程并行执行任务,同时使用互斥锁等同步机制避免数据竞争问题,保证程序的正确性。
4. ASyncSocket库的作用:在Windows平台上,ASyncSocket库提供了异步套接字编程的支持,允许在单个线程中处理多个网络事件,极大地简化了网络编程。在MSN Messenger模仿程序中,ASyncSocket库被用来处理TCP/IP通信,...
多线程可以在单个进程中并发执行,提高处理器利用率。 3. **线程的优势**:相比于进程,线程创建和销毁更快,上下文切换成本更低,更利于多核处理器的并行计算。 4. **线程同步与互斥**:为了保证数据一致性,线程间...