linux下一个线程占用多少内存

本文深入探讨了MySQL线程的栈空间管理,包括Windows与Linux平台下的线程限制,以及Java与Solaris等环境下的栈空间默认值。重点介绍了如何通过`pthread_attr_getstacksize`和`pthread_attr_setstacksize`方法来查看和调整线程栈空间大小,以应对大数据量处理应用中的内存需求。

群里讨论出mysql的问题,因为mysql是一个连接建立一个线程的,这就涉及到mysql可以建立多少个线程。

无论是windwos 还是linux ,每个线程都有自己独立的stack,每个stack 都占用一定的空间。
windwos 默认的是1M,这个在exe中可以看到,也可以编译时指定。linux默认使用pthread.h中的PTHREAD_STACK_SIZE,这和glibc的编译有关系,
这样说明linux 可以使用更多的线程。
int __pthread_attr_setstacksize(pthread_attr_t *attr, size_tstacksize)
{
#ifdef FLOATING_STACKS
 
  if (__pthread_max_stacksize == 0)
   __pthread_init_max_stacksize ();

  if (stacksize >__pthread_max_stacksize)
    returnEINVAL;
#else
 
  if (stacksize >STACK_SIZE)
    returnEINVAL;
#endif

 
  if (stacksize __stacksize = stacksize;
  return 0;
}


对于java ,Solaris 默认  256k for 32-bit intel, 512Kfor 32-bit sparc, 1M for 64-bit sparc
          linux 可以使用-Xss,默认使用ulimit-s的值。  
先来讲说线程内存相关的东西,主要有下面几条:
进程中的所有的线程共享相同的地址空间。
任何声明为static/extern的变量或者堆变量可以被进程内所有的线程读写。
一个线程真正拥有的唯一私有储存是处理器寄存器。
线程栈可以通过暴露栈地址的方式与其它线程进行共享。
下面的网上的代码
    有大数据量处理的应用中,有时我们有必要在栈空间分配一个大的内存块或者要分配很多小的内存块,但是线程的栈空间的最大值在线程创建的时候就已经定下来了,如果栈的大小超过个了个值,系统将访问未授权的内存块,毫无疑问,再来的肯定是一个段错误。可是没办法,你还是不得不分配这些内存,于是你开会为分配一个整数值而动用malloc这种超级耗时的操作。当然,在你的需求可以评估的情况下,你的需求还是可以通过修改线程的栈空间的大小来改变的。

下面的我们用pthread_attr_getstacksize和pthread_attr_setstacksize的方法来查看和设置线程的栈空间。
注意:
     下面的测试代码在我自己的机子上(ubuntu6.06,ubuntu6.10,redhat 9,gentoo)通过了测试,但是很奇怪的是在我同事的机子上,无论是改变环境,还是想其它方法都不能正常的运行。在网上查了一下,很多人也存在同样的问题,至今不知道为何。

linux线程的实现方式决定了对进程的限制同样加在了线程身上:)所以,有问题,请参见<pthread>
#include <pthread>

 


void *thread_routine (void *arg)
{
    printf ("Thethread is heren");
 char p[1024*1024*15];
 int i=1024*1024*15;


 while(i--)
 {
  p[i] = 3; 
 }

 printf( "Get 15M Memory!!!n" );
 
 
 char p2[ 1024 * 1020 + 256 ];
 memset( p2, 0, sizeof( char ) * ( 1024 * 1020 +256 ) );
 printf( "Get More Memory!!!n" );
    returnNULL;
}

int main (int argc, char *argv[])
{
    pthread_tthread_id;
   pthread_attr_t thread_attr;
    size_tstack_size;
    intstatus;

    status =pthread_attr_init (&thread_attr);
    if (status!= 0)
       printf ("Create attr");

    status =pthread_attr_setdetachstate (
       &thread_attr, PTHREAD_CREATE_DETACHED);

    if (status!= 0)
       printf ( "Set detach");
 
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
   status =pthread_attr_getstacksize (&thread_attr,&stack_size);
    if (status!= 0)
       printf ( "Get stack size");
    printf("Default stack size is %u; minimum is %un",
       stack_size, PTHREAD_STACK_MIN);

    status =pthread_attr_setstacksize (
       &thread_attr,PTHREAD_STACK_MIN*1024);
    if (status!= 0)
       printf ("Set stack size");
 
   status =pthread_attr_getstacksize (&thread_attr,&stack_size);
    if (status!= 0)
       printf( "Get stack size");
    printf("Default stack size is %u; minimum is %un",
       stack_size, PTHREAD_STACK_MIN);
#endif
 int i = 5;
 while(i--)
 {
  status = pthread_create (
  &thread_id,&thread_attr, thread_routine, NULL);
  if (status != 0)
   printf ("Createthread");
 }

   getchar();
    printf("Main exitingn");
    pthread_exit(NULL);
    return0;
}


 

看看执行过程:

gcc -pthread -g -DDEBUG -lrt  -o thread_attrthread_attr.c
./thread_attr
Default stack size is 8388608; minimum is16384        //默认的栈大小为8M
Default stack size is 16777216; minimum is16384     //设置后的结果为16M
The thread is here
The thread is here
The thread is here
The thread is here
The thread is here
Get 15M Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get 15M Memory!!!
Get More Memory!!!
Get More Memory!!!
Get 15M Memory!!!
Get More Memory!!!

Mainexiting</pthread></pthread>


<think> 我们正在讨论线程创建时的内存占用问题,特别是Java和C++中的线程内存消耗。 根据引用内容,线程内存占用主要包括两部分: 1. 线程对象本身的大小(在Java中是Thread对象,在C++中是std::thread对象) 2. 线程栈的大小(这是操作系统为线程分配的栈空间) 在Java中: - 线程栈的大小可以通过JVM参数指定(如-Xss),默认值取决于JVM和操作系统,通常为512KB到1MB(64位系统可能更大)[^1][^3]。 - 线程对象本身在堆中分配,大小固定(通常为几百字节),但线程执行过程中还会持有对象、锁等,这部分可能占用额外的堆内存。 在C++中: - std::thread对象本身的大小是固定的(通常为几个指针大小,例如在64位系统上可能是8字节,但具体实现可能不同)[^2]。 - 线程栈的大小同样由操作系统和编译器设置决定(例如Linux上默认可能是8MB,可通过ulimit或pthread_attr_setstacksize设置)[^2][^4]。 另外,创建线程时操作系统还需要为线程分配一些内核资源(如线程描述符),这也会消耗少量内存(通常在KB级别)[^3][^4]。 因此,创建一个线程的总内存占用可以近似表示为: $$ \text{总内存} = \text{线程对象大小} + \text{线程栈大小} + \text{内核数据结构开销} $$ 具体数值: - Java:线程对象本身(约几百字节到1KB)+ 线程栈(默认512KB-1MB)+ 内核开销(几KB)[^1][^3][^4] - C++:std::thread对象(几个指针大小,比如8字节)+ 线程栈(默认可能8MB)+ 内核开销(几KB)[^2][^4] 注意:线程栈是预先分配的,所以即使线程没有使用那么多栈空间,也会占用这些内存。 如何查看? - Java:可以通过JVM参数设置栈大小,并通过工具(如jstack、jmap)查看线程信息[^1]。 - C++:可以通过pthread_attr_setstacksize设置栈大小,通过系统工具(如pmap)查看内存映射[^2]。 总结:线程内存占用主要由栈大小决定,而栈大小是可配置的,但操作系统有默认值。在内存敏感的应用中,应合理设置栈大小以避免浪费。 </think> ### 线程内存占用分析 创建一个线程内存占用由三部分构成,其大小受编程语言、操作系统和配置参数影响: #### 一、核心内存组成 1. **线程栈空间** - Java:默认栈大小 `$512KB-1MB$` (64位JVM)[^1],可通过 `-Xss` 调整: ``` java -Xss256k MyApp // 设为256KB ``` - C++:Linux默认 `$8MB$` (通过 `ulimit -s` 查看)[^4] - 计算公式: $$ \text{栈内存} = \text{线程数} \times \text{栈大小} $$ 2. **线程描述符** - JVM内部数据结构:约 `$1-2KB$`[^3] - 操作系统级描述符:`$0.5-2KB$` (如Linux的task_struct)[^4] 3. **线程对象开销**[^1][^2] | 语言 | 对象大小 | 说明 | |--------|---------------|-----------------------| | Java | `$500-1000B$` | Thread对象堆内存占用 | | C++ | `$20-100B$` | std::thread对象本身 | #### 二、影响因素 1. **操作系统差异** - Linux轻量级进程(LWP)共享内存映射,Windows线程开销更大[^4] - 栈大小下限:`$128KB$` (Linux) / `$64KB$` (Windows)[^3] 2. **内存对齐开销** 实际占用需按页对齐(通常 `$4KB$` 页),导致: $$ \text{实际内存} \geq \lceil \frac{\text{理论内存}}{4096} \rceil \times 4096 $$ 3. **运行时增长** 局部变量和调用栈深度可能导致额外分配,极端情况触发 `StackOverflowError`[^1] #### 三、内存计算示例 Java线程默认配置: $$ \begin{align*} \text{总内存} &= \text{栈大小} + \text{描述符} + \text{对象} \\ &= 1MB + 2KB + 800B \\ &\approx 1028KB \end{align*} $$ #### 四、优化建议 1. **栈大小调优** ```c // C++设置栈大小示例 pthread_attr_t attr; pthread_attr_setstacksize(&attr, 131072); // 128KB ``` 2. **线程池控制** 避免频繁创建销毁线程,复用线程资源[^3] 3. **监控工具** - Java: `jcmd <pid> Thread.print` - Linux: `pmap -x <pid>` 查看实际映射 > ⚠️ 注意:32位系统单个进程线程数受限于 `$3GB$` 用户空间,100线程默认栈配置可能耗尽内存[^1][^4]。 --- ### 相关问题 1. 如何精确测量Java应用中单个线程内存消耗? 2. 线程栈大小设置过小会导致哪些运行异常? 3. 不同操作系统(Linux/Windows)的线程实现有何内存差异? 4. 线程池技术如何降低线程创建的内存开销? 5. 在嵌入式系统中优化线程内存占用的实践方法有哪些?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值