多线程 - 你知道线程栈吗 http://blog.csdn.net/gykimo/article/details/9132157

转载 2015年11月19日 19:57:38

目录(?)[+]

问题

1. local 变量的压栈和出栈过程
void func1(){
    int a = 0;
    int b = 0;
}
系统中有一个栈顶指针,每次分配和回收local 变量时,其实就是移动栈指针。

2. static local变量的分配风险
void func2(){
    static int a = 0;
}
这个变量a可能会被分配多次,因为如果func2可能同时被多个线程调用,也就是函数在分配内存时是可能出现线程切换的。

问题:

void func3(){
int a;
int b;
}

void func4(){
int c;
int d;
}
假设,func3和func4分别被两个线程调用,并且func3先于func4执行,并且4个变量压栈的顺序分别是a、b、c、d。按照上面第1个说明,这个时候栈顶指针指向d。
如果,这个时候func3先执行完,那么这个时候,系统要回收b和a,但是b并不在栈顶,所以,无法移动栈顶指针,所以,b和a无法回收。最复杂的情况可能如下,压栈的顺序是a、c、d、b,这个时候b可以正常回收。当要回收a时,会不会误把d当作a给回收了?应该怎么解释这个问题呢。
显然,事实上并非上面所述,因为线程里有一个很重要的属性stacksize,它让我们隐约感觉到,线程是拥有私有的栈空间的,如果这样,abcd的压栈出栈就不会有问题了,因为他们并不保存在一起。


pthread线程栈

  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3.   
  4. void* thread1(void* a)  
  5. {  
  6.     char m[8388608];  
  7.     printf("thread1\n");  
  8. }  
  9.   
  10. int main(){  
  11.     pthread_t pthread_id;  
  12.     pthread_attr_t thread_attr;  
  13.     int status;  
  14.   
  15.     status = pthread_attr_init(&thread_attr);  
  16.     if(status != 0)  
  17.         printf("init error\n");  
  18.   
  19.     size_t stacksize = 100;  
  20.     status = pthread_attr_getstacksize(&thread_attr, &stacksize);  
  21.     printf("stacksize(%d)\n", stacksize);  
  22.     //printf("size(%d)\n", sizeof(int));  
  23.   
  24.     status = pthread_create(&pthread_id, NULL, thread1, NULL);  
  25.     while(1)  
  26.     {}  
  27.     return 0;  
  28. }  

运行结果:

stacksize(8388608)
段错误

分析

pthread_attr_getstacksize可以获得线程的私有栈的大小,我这个机器是8388608字节,为8M,也就是私有栈最大是8M,所以,创建的一个线程函数里有个局部数组长度为8M,显示段错误(虽然数组大小和私有栈一样大,但是私有栈除了分配局部变量外,还要保存一些管理信息,所以肯定要小于8M),如果将数组长度减小一定的值,就可以看到thread1函数的打印信息。


pthread线程内存布局



我们从图上可以看出,两个线程之间的栈是独立的,其他是共享的,所以,在操作共享区域的时候才有可能出现同步需要,操作栈不需要同步。

最后我们知道,pthread也提供了私有堆机制,关于私有堆机制在以后说明。

证明StringBuffer线程安全,StringBuilder线程不安全

证明StringBuffer线程安全,StringBuilder线程不安全证明StringBuffer线程安全StringBuilder线程不安全 不多说直接列代码 解释 结果 源码分析不多说直接列代...
  • litterfrog
  • litterfrog
  • 2017年08月07日 22:40
  • 224

http://blog.csdn.net/zhshulin/article/details/37956105

使用SSM(Spring、SpringMVC和Mybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方。之前没有记录SSM整合...
  • u014205268
  • u014205268
  • 2016年06月26日 17:06
  • 393

java自定义栈(链表实现)

使用链表来实现栈比用数组更加方便,也易于节省空间,因为栈只能在栈顶进行操作,不需要进行随机访问栈元素首先实现栈接口IStack,提供出栈、入栈、获取栈顶元素、判断是否为空以及清空栈等基本功能:...
  • jdhanhua
  • jdhanhua
  • 2011年07月12日 10:45
  • 2359

转载自:http://blog.csdn.net/lmj623565791/article/details/24015867

1、请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系。 拿主线程来说,主线程启动时会调用Looper.prepare()方法,会初始化一个...
  • zhi_liyan
  • zhi_liyan
  • 2015年02月10日 10:38
  • 719

http://m.blog.csdn.net/article/details?id=46348827

1.EraseBk()函数不响应,没有加初始化函数. 2.加载图片是白板,初始化函数里的语句有问题. 3.子窗口在父窗口外面,或者移子窗口位置大小子窗口不听话,是因为子窗口属性没有设置为Child...
  • suixinger1
  • suixinger1
  • 2016年10月10日 15:29
  • 6459

http://blog.csdn.net/ithomer/article/details/6688883

android中获取屏幕的长于宽,参考了网上有很多代码,但结果与实际不符,如我的手机是i9000,屏幕大小是480*800px,得到的结果却为320*533 结果很不靠谱,于是自己写了几行代码,亲测...
  • liyong625175856
  • liyong625175856
  • 2014年06月11日 14:33
  • 780

Centos7在虚拟机中连接网络及静态IP设置

本文转载自:http://blog.csdn.net/a785975139/article/details/53023590 最近在VMware虚拟机里玩Centos,装好后发现上不了网。经过一...
  • qq_30770095
  • qq_30770095
  • 2018年01月25日 09:04
  • 134

Winform下KeyDown,KeyPress,KeyUp事件的总结

几篇将的比较好的文章: http ://blog.csdn.net/simpkan/article/details/6087727 http://blog.csdn.net/xiash...
  • anlidengshiwei
  • anlidengshiwei
  • 2014年06月25日 17:23
  • 939

移动互联周考面试题 http://blog.csdn.net/w00w12l/article/details/8143591?locationNum=14&fps=1

这是我的周考面试题 需要把面试题好好复习下 这样才会在工作有个好的发展 http://blog.csdn.net/w00w12l/article/details/8143591?locati...
  • hanguomingxing
  • hanguomingxing
  • 2017年07月24日 11:50
  • 420

http://blog.csdn.net/shootyou/article/details/6093562

http://blog.csdn.net/shootyou/article/details/6093562   Nginx介绍和安装 一个简单的配置文件 模块介绍 ...
  • ywh147
  • ywh147
  • 2013年03月18日 18:12
  • 4717
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多线程 - 你知道线程栈吗 http://blog.csdn.net/gykimo/article/details/9132157
举报原因:
原因补充:

(最多只允许输入30个字)