很多现代操作系统中,一个进程的(虚)地址空间大小为4G,分为系统空间和用户空间两部分,系统空间为所有进程共享,而用户空间是独立的,一般WINDOWS进程的用户空间为2G。

  一个进程中的所有线程共享该进程的地址空间,但它们有各自独立的(私有的)栈(stack),Windows线程的缺省堆栈大小为1M。堆(heap)的分配与栈有所不同,一般是一个进程有一个C运行时堆,这个堆为本进程中所有线程共享,Windows进程还有所谓进程默认堆,用户也可以创建自己的堆。

堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。

栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。

参考资料: 进程线程与栈 堆的关系(转)

一篇文章:

最初涉及多线程程序涉及的时候经常会出现一些令人难以思议的事情,用堆和栈分配一个变量可能在以后的执行中产生意想不到的结果,而这个结果的表现就是内存的非法被访问,导致内存的内容被更改。

理解这个现象的两个基本概念是:在一个进程的线程共享堆区,而进程中的线程各自维持自己堆栈。

另一运行机制就是如果声明一个成员变量 如 char Name[200],随着这段代码调用的结束,Name在栈区的地址被释放,而如果是 char * Name = new char[200]; 情况则完全不同,除非显示调用delete否则 Name指向的地址不会被释放。

理解了线程对 堆栈 的可见性,和内存管理机制就能推测出笔者伊始提出的现象。

用一个 实例来深入理解这种机制。

在线程 1 中,

A ()

{

B();

C();

}

B()

{

栈 or 堆分配变量 V;

将V的地址插入 公共队列;

}

线程 2 中:

D()

{

while(1)

{

处理公共队列;

}

}

在B中如果用栈区 即采用临时变量的机制分配声明V和堆区,而者的结果是不同的。如果用栈区,如果变量地址为Am1-Am2这么大,退出B调用时候这段地址被释放,C函数可能将这段内存改写;这样当D执行的时候,从内存Am1-Am2中读取的内容就是被改过的了。

而如果用New(堆)分配,则不会出现那样的情况,因为没有显示对用delete并且堆对于线程共享,即2线程可以看到1线程在堆里分配的东西,所以不会发生误写。

多线程中堆和栈区别的深入解析相关推荐

  1. C++中堆和栈的完全解析

    C++中堆和栈的完全解析 内存分配方面: 堆: 操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删 除,并 ...

  2. Java中堆、栈、常量池等概念解析

    Java中堆.栈.常量池等概念解析 程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器.这是最快的保存区域,因为它位于和其他所有 ...

  3. 当初我要是这么学习Java多线程就好了「附图文解析」

    文章目录 1. 概念篇 1.1 认识进程 1.2 进程性质 1.3 操作系统如何管理进程 1.4 多线程和多进程 1.5 时间片 1.6 并发与并行 1.7 内核态与用户态 1.8 进程中的上下文 1 ...

  4. c++中堆、栈内存分配概念示例讲解

    首先来看看主要有几种程序内存分配: 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stack)- 由编译器自动分配释放 ,存放函数参数值,局部变量值等.其操作方式类似于数据结构中栈. 2 ...

  5. VMware 虚拟化编程(8) — 多线程中的 VixDiskLib

    目录 目录 前文列表 多线程注意事项 多线程中的 VixDiskLib 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化 ...

  6. android串口补位,Rust多线程中的消息传递机制

    代码说话. use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() { let (tx, rx) = mpsc ...

  7. 多线程中的应用之队列(queue)

    队列queue 多应用在多线程中,对于多线程访问共享变量时,队列queue是线程安全的. 从queue队列的实现来看,队列使用了1个线程互斥锁(pthread.Lock()),以及3个条件标量(pth ...

  8. c++中堆、栈内存分配

    转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stac ...

  9. 内存中“堆”和“栈”的区别

    内存中"堆"和"栈"的区别: 程序中用来存放数据的内存分为四块,分别是: 1.全局区(静态区)(static):全局变量和静态变量都存储在这块区域,与其他变量的 ...

最新文章

  1. Java项目:仿天猫网上商城项目(java+jsp+servlet+mysql+ajax)
  2. mysql 修复_mysql修复表的三个方法
  3. Firefox Quantum支持跨浏览器插件架构
  4. IP地址的正则表达式
  5. Oracle/mysql联合查询union、union all
  6. 一分钟解决“仅限中国大陆地区播放”
  7. [SQL实战]之从titles表获取按照title进行分组
  8. 报告 | 73%的“落伍”开发者说:明年要学AI技术
  9. 让textbox紧贴IME
  10. 从哥尼斯堡“七桥问题”到盖洛普“优势识别器”
  11. Linux平台开源浏览器
  12. Snapper转换器的捕捉类型
  13. 多种好看好玩的词云例子Example
  14. 学计算机课业压力,关于学习负担、学业负担及课业负担的一段解释
  15. 用对线阶段数据分析和预测《英雄联盟》的游戏结果
  16. XTransfer又双叒叕拿奖,XTransfer外贸收款这么靠谱吗?
  17. 开发一个短信推送工具需要怎么做
  18. mysql中esc是什么意思_esc按钮是什么意思
  19. 给ofo共享单车撸一个微信小程序
  20. OpenStack Kolla-Ansible部署Designate域名解析服务DNS服务DNSaas

热门文章

  1. java for 循环执行顺序
  2. matlab watershed函数简单实现_函数指针方法实现简单状态机(附代码)
  3. java edittext 输入监听_Android应用开发之Android EditText 监听用户输入完成的实例
  4. Linux webkit截图,CutyCapt 跨平台使用 WebKit 内核网页截图工具 - 文章教程
  5. Linux路由界面设置,nuxt中如何配置页面路由
  6. 背景图层和普通图层的区别_ps:图层有多少种类?我已经列出来了,学不学就看你自己了...
  7. java string set_Java StringJoiner setEmptyValue()用法及代码示例
  8. mysql数据库localhost已断开_完美解决MySQL通过localhost无法连接数据库的问题
  9. HDLBits答案(16)_Verilog有限状态机(3)
  10. 商业逻辑12讲之管理思维的逻辑