堆和堆栈
多线程中堆栈的区别
首先在这里澄清堆和栈。堆和栈是不同的数据结构,参看数据结构部分。当我们结果这个两个字使用的时候:堆栈
通常指栈。
实际上栈(Stack)有三种含义,根据使用情景区分不同的含义。
栈的三种含义:
数据结构中的栈
是一种数据的存放方式,后进先出,LIFO。具体参考数据结果部分。调用栈 call stack
指代码的运行方式。函数在调用过程中是一层一层叠加的。最上层的调用先结束然后移除。句一个简单的例子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def a():
print('I am a')
def b():
a()
print('I am b')
def c():
b()
a()
print('I am c')
if __name__ == '__main__':
c()
I am a
I am b
I am a
I am c那么调用c后,c函数压入栈,然后调用b,b函数入栈,发现b函数也调用了a,a入栈,a打印’I am a’,调用结束,a出栈。b打印’I am b’,调用结束,出栈。回到c,c调用a,a入栈,打印’I am a’,结束出栈,最后打印’I am c’,b出栈。
存放数据的一种内存区域
程序在运行过程中,需要内存空间存放数据。操作系统会划分出不同的内存空间,一种叫栈,一种叫堆。那么它们具体是什么,这就是本节要讨论的。
Stack Vs Heap
Heap
分为全局(所有没有分配的空间)和局部Heap(用户分配的空间)。在操作系统对进程初始化时为期分配Heap,当运行时需要再向系统申请,用完要归还操作系统,否则会造成内存泄漏Stack
栈是线程独占,保存线程运行状态和局部变量。线程切换时会导致栈的切换。
存储结构上
Stack是有结构的,每个区块有一定的次序存放,可以明确每个区块的大小。Heap是没有结构的,数据可以任意存放。由于Stack的有序性,Stack的寻址效率高于Heap。区块大小这部分参考内存管理。内存线程进程上
操作系统会为每个进程分配一个Heap,为进程中的每个线程分配一个Stack。根据线程和进行的关系,可以理解,每个线程独占自己的Stack,但共享进程的Heap。运行过程中,进程需要更多的内存空间,可以向操作系统申请,申请到的内存区就是Heap的一部分。线程启动后,Stack的大小是固定的,这可以解析为什么函数递归深度过深会导致栈溢出。和栈溢出的一个相似的现象是内存溢出,内存溢出是发生在Heap中。讨论
1 | def stackoverflow(): |
值得注意,当函数退出时,该obj对象不会消失,而是靠垃圾回收算法负责清理。