多线程内存管理

面试总结------Java内存管理多线程 面试总结——Java内存管理多线程1. 什么是线程?什么是进程?同一进程下的线程共享线程:程序在执行过程中,能够执行程序代码的一个执行单元,一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。在Java语言中有4种状态:运行、就绪、挂起、结束。进程:指一段正在执行的程序。线程有时也被称为轻量级进程,它是程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内存空 阅读详情

  原文:http://yachang.wang.blog.163.com/blog/static/35551220200762753057335/

 

  假设有一个进程,创建了两个线程A、B,线程A在堆上分配了一块内存空间,通知传指针的方式在B中使用,使用完后释放块,这时就会出错,因为线程B不能释放线程A堆上的内存空间,一些网友对此也有一些看法。

       “有点经验可以告诉你,每个线程都有自己的堆栈,而它们共享进程的一个全局堆,NEW是在线程的局部堆上分配(实际上每个函数都是这样),在线程中用 new分配的内存不能在另一个线程中用delete删除(因为这两个函数都只能处理自己的堆)要完成这个功能必须用HeapAlloc函数在全局堆上进行 操作。至于内存管理我的感觉是看看编译原理,尤其是影印版的会很清楚,因为程序运行中内存的动态分配操作系统的书籍 只是从系统管理的角度来阐述的,是一个问题的两个方面。”

       “在程序启动的时候把你要NEW的内存NEW成一个链表放起来,比如先NEW一个链表,结点就是要用的内存,然后在需要用的时候从链表里取一个出来,用完了放回链表 最后程序退出的时候销毁这个链表。去找找有关内存池的资料吧”

        “_beginthread(ex)与CreateThread的主要不同是对C标准库函数的支持不同,在CreateThread中使用C标准库函数是 不安全的(据M$的说法,如果CreateThread线程创建失败,使用C标准库函数会导致少量内存泄漏,但总而言之,不够安全)。Win32中C++ 算符new/delete实际上是通过在进程全局堆中分配实现的,如果为安全性考虑,可以用HeapCreate创建局部堆,然后通过HeapAlloc /HeapFree分配,这样如果有某些错误的话(如数组越界)不至于影响到全局堆中的数据。我个人觉得的用AfxBeginThread()对C++的 语法支持较好,而且它内部调用的是_beginthreadex,   可是他返回的是CWinThread对象的指针,可能对你不太适用。”

        “同一进程内的所有线程共享进程地址空间,每个线程有独立的堆栈,一个线程可以访问另一个线程的堆。”

        “第一次听到线程堆栈的地址空间这个叫法,所以恕我不能明白你的意思。在很多现代操作系统中,一个进程的(虚)地址空间大小为4G,分为系统(内核?)空 间和用户空间两部分,系统空间为所有进程共享,而用户空间是独立的,一般WINDOWS进程的用户空间为2G。   
          一个进程中的所有线程共享该进程的地址空间,但它们有各自独立的(/私有的)栈(stack),Windows线程的缺省堆栈大小为1M。堆 (heap)的分配与栈有所不同,一般是一个进程有一个C运行时堆,这个堆为本进程中所有线程共享,windows进程还有所谓进程默认堆,用户也可以创 建自己的堆。用操作系统术语,线程切换的时候实际上切换的是一个可以称之为线程控制块的结构(TCB?),里面保存所有将来用于恢复线程环境必须的信息,包括所有必须保存的寄存器集,线程的状态等。 ”

        “有关内存管理问题,很多书上都有比较详尽的介绍,基本上也就如wzwind(风的脚印)所述。内存分配主要分为堆栈(stack)内存分配和堆 (heap)内存分配。当你定义了一个局部变量时,系统会自动在堆栈中为该变量分配空间,当程序运行到堆栈变量的作用范围之外时,空间会自动释放。而堆则 是在程序代码段 和堆栈之外的内存段,这部分的内存是可以动态分配的,需要程序员来管理(分配和释放)。对于同一个进程的多个线程而言,它们之间是共享同一内存空间的,虽 然每个线程都有自己的堆栈,但它们使用同一块堆。你可以把线程理解为一个函数或过程,它可以有自己的局部变量,而用new分配的变量相当于全局变量,可供 同一进程的其它线程共享,所以线程退出后,应及时释放,否则这段空间就一直被你占用着。”

        根据CSDN上网友的看法,在查阅了相关书籍但做了代码测试的基础上,我也在这里提出自己的观点。

  1. 首先要澄清的是堆栈(STACK)和堆(HEAP)的区别,中文将STACK译为“堆栈”我个人认为不是很科学,不如直接译为“栈”,这样与 HEAP更容易区分。这里讨论的栈与堆是操作系统层面的,栈是系统自动管理与分配的内存资源,分配与回收的效率高,常用于函数调用时参数传递,在线程切换 时要进行栈切换;堆由程序员自行分配与释放,C++中用NEW与DELETE分配与释放,在堆上分配与回收内存更灵活,但是效率与栈操作低了一点,并且一 定要注意回收,不然会导致内存泄漏。
  2. 一个进程有一个全局的HEAP,创建的每个线程都有自己的STACK,线程创建时可以自定义栈大小,默认情况下WIN32是1MB,所以线程间是栈安全的,这样,在一个线程中分配的内存可以在另一个线程中释放,后面我会给出代码验证。
  3. 在下面的代码中,我会创建两个线程,一个全局的Buffer,采用FIFO队列实现,一个线程向队列中写数据,一个线程从线程中读数据,采用事件通知策略,用条件互斥量避免数据竞争。

#include <process.h>
#include <windows.h>
#include <queue>
#include <stdio.h>

using namespace std;

DWORD WINAPI ThreadWrite(LPVOID lParam);
DWORD WINAPI ThreadRead(LPVOID lParam);

queue<char *> Buffer;

HANDLE m_hMutexBuffer;
HANDLE m_hEventBuffer;

void main()
{
 m_hMutexBuffer = CreateMutex(NULL, FALSE, NULL);
 ReleaseMutex(m_hMutexBuffer);

 m_hEventBuffer = CreateEvent(NULL, TRUE, FALSE, NULL);
 
 HANDLE m_hThreadWrite = CreateThread(NULL, 0, ThreadWrite, NULL, 0, 0);
 HANDLE m_hThreadRead  = CreateThread(NULL, 0, ThreadRead,  NULL, 0, 0);
 
 HANDLE HandleList[2];
 HandleList[0] = m_hThreadWrite;
 HandleList[1] = m_hThreadRead;
 
 WaitForMultipleObjects(2, HandleList, TRUE, INFINITE);
}

DWORD WINAPI ThreadWrite(LPVOID lParam)
{
 if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutexBuffer, 100))
 {  
  char *Item = new char[20];
  strcpy(Item, "Hello World!");
  Buffer.push(Item);
  ReleaseMutex(m_hMutexBuffer);
  printf("0x%08x/n", Item);
  printf("0x%08x/n", &Item);
  SetEvent(m_hEventBuffer);  
  Sleep(10);
 } 
 return 0;
}

DWORD WINAPI ThreadRead(LPVOID lParam)
{
 if (WAIT_OBJECT_0 ==WaitForSingleObject(m_hEventBuffer, INFINITE))
 {
  if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutexBuffer, 100))
  {
   char * _Item = Buffer.front();
   Buffer.pop();
   if (Buffer.empty())
   {
    ResetEvent(m_hEventBuffer);
   }
   ReleaseMutex(m_hMutexBuffer);

   printf("%s/n", _Item);

   printf("0x%08x/n", _Item);
   printf("0x%08x/n", &_Item);

   Sleep(10);
   
   delete []  _Item;

   _Item = NULL;
  }
 } 
 return 0;
}

 

在终端打印如下:

0x00372d68

0x0051ffb0

Hello World!

0x00372d68

0x0061ffb0

可见写线程中的Item与读线程_Item地址不同,在各自的栈空间上分配,相差0x00100000大小的地址空间,而Item与_Item指向相同的内存空间,这个内存空间是在进程的全局堆空间上分配的。

delete 函数只能调用一次,因为Item 和 _Item是在栈上分配的,在线程中由系统自己回收,但二者指向相同的内存空间,因此只能释放一次。利用这个特性,我们可以很方便地在线程间离开内存通信,并可以很好地解决分配与回收的问题。

 

 

深入了解内存管理多线程编程 本文深入探讨了内存管理的基础知识,包括内存保护、查询和保留机制,以及Windows 2000与Windows 95/98在内存管理上的区别。同时,文章还详细解读了多线程编程概念、线程池的应用和多线程安全机制,为编程实践提供了理论支持。 阅读详情

相关推荐

Objective-C内存管理多线程编程深入解析

本文深入探讨了Objective-C中的内存管理多线程编程的高级特性。首先,解释了Objective-C中的引用计数机制和僵尸对象的概念,以及如何使用僵尸对象进行调试。接着,讨论了避免使用retainCount的原因,特别是在ARC环境下。最后,介绍了多线程编程中块(blocks)和Grand Central Dispatch(GCD)的基本概念及其在现代编程中的重要性。

weixin_35592186的博客 370

C++内存共享, 与多线程同步通信

C++内存共享,与多线程同步

weixin_43202230的博客 2237

Objective-C内存管理多线程编程技巧

本文深入探讨了Objective-C中的内存管理机制,特别是僵尸对象的处理与调试方法,以及引用计数(retainCount)的局限性。同时,文章介绍了多线程编程的重要概念,包括块(blocks)和大中央调度(Grand Central Dispatch,简称GCD),并探讨了如何在现代Objective-C编程中有效地使用这些技术。

weixin_35677363的博客 535

c语言多线程性能调优,C++性能优化(八)——内存分配机制

C++性能优化(八)——内存分配机制一、操作系统内存布局1、32位系统经典内存布局Linux Kernel 2.6.7前版本采用的默认内存布局形式如下:(1)32操作系统中,loader将可执行文件的各个段次依次载入到从0x80048000(128M)位置开始的空间中。应用程序能够访问的最后地址是0xbfffffff(3G)的位置,3G以上的位置是给内核使用的,应用程序不能直接访问。(2)内存布局...

weixin_29854481的博客 1666

[C++对象模型][5]堆栈与函数调用

一 C++程序内存分配 1) 在栈上创建。在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,一般使用寄存器来存取,效率很高,但是分配的内存容量有限。 2) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete来释放内存。动态内存的生存...

weixin_34281537的博客 365

多线程是可以同时读取同一个内存数据的

记录一下: 多线程如果只是读取同一块内存区域的数据,没必要设置成同步线程,线程同步的目的是为了防止同一时间多个线程要修改数据,造成数据错误。所以:如果线程只是访问,完全没必要线程同步 ...

weixin_42227520的博客 5123

多线程读取同一个内存数据会出错吗

多线程是否可以同时读取同一内存变量? 多线程是否可以同时读取同一内存变量?只是对他进行读取不进行写入修改 那么在多线程中是否会因此而出错? itljl 2012-12-23 00:14 读可以,修改不可以。 华玉欣 2012-12-23 02:40

lien0906的专栏 1万+

C++:多线程内存管理的思考

C++:多线程内存管理的思考

ERAtime的博客 856

内存管理多线程

准备写一篇关于《内存管理多线程》的文章,以总结最近一个月的研究结果……

游戏里的羔羊-Baickl 1312

Python内存管理多线程

1. 内存管理机制 1.1 赋值语句的内存分析 赋值语句都是“引用”,可以这样理解,但是,这种“引用”是可以改变指向的 非赋值语句时 对于可变类型的数据, 创建一块新内存(Set、Dictionary、List) 对于不可变数据类型 简单数据,存在使用“引用”,不存在创建新内存 复杂大数据,创建新内存 1.2 垃圾回收机制 1.2.1 垃圾自动回收 以引用计数为主,分代收集为辅 # 引用计数 # 1.每个对象都有存有指向该对象的引用总数 # 2.查看某个对象的引用计数 --&gt

weixin_46005735的博客 1395

多线程内存管理更加热门些。

多线程管理

远方雪的专栏 218

C++性能优化面试:内存管理多线程

本文详细阐述了C++性能优化中的内存管理多线程两个方面。内存管理涉及内存分配与回收、内存泄漏检测与优化;多线程涉及线程创建与同步、线程优化与调度。在面试中,掌握这些知识点,能够展示出自己对C++性能优化的深入理解和实践经验。为了提高C++程序的性能,我们需要不断学习和实践内存管理多线程技术。在未来的研究中,可以进一步探索新型内存管理技术和多线程调度策略,以实现更高的程序性能。建议与未来方向:通过实际项目实践,积累内存管理多线程编程经验。关注C++新版本的内存管理多线程特性,掌握新型编程模型。

2501_92487957的博客 411

cocos2dx多线程以及线程同步 与 cocos2dx内存管理多线程问题

cocos2dx多线程以及线程同步 与 cocos2dx内存管理多线程问题 分类: 移动研发 COCOS2DX 移动ANDROID研发 IOS研发2013-11-07 16:17 7573人阅读 评论(5) 收藏 举报 目录(?)[+] cocos2d-x引擎在内部实现了一个庞大的主循环,每帧之间更新界面,如果耗时的操作放到了主线

TheClimb的池塘 703

c语言内存管理线程,C语言多线程内存管理模块.doc

C语言多线程内存管理模块C语言多线程内存管理模块摘要:一个多线程动态内存管理模块,可以有效地检测C语言中内存泄漏和内存越界等错误。原理分配通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、行号,并用一个HASH表来保存所有节点。越界检测为了检测写越界的错误,在用户申请的内存前后各增加了一定大小的内存作为监测区域,并初始化成预定值...

weixin_33959449的博客 350

多线程应用在鸿蒙 HarmonyOS Next 中的内存管理与 GC 实战

本文旨在深入探讨华为鸿蒙HarmonyOS Next系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在构建高性能应用时,尤其是需要处理大量并发任务的场景中,多线程架构显得尤为重要。

same4869的博客 1255
上一篇: C结构体中的函数指针与函数
下一篇: 堆和栈的区别
wozaiwogu
博客等级 码龄18年 10粉丝 17原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值