当前位置: 首页 > news >正文

线程的共享资源和私有资源

线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。

 
    进程拥有这许多共性的同时,还拥有自己的个性。有了这些个性,线程才能实现并发性。这些个性包括:

    1.线程ID
      每个线程都有自己的线程ID,这个ID在本进程中是唯一的。进程用此来标
   识线程。
 
    2.寄存器组的值
       由于线程间是并发运行的,每个线程有自己不同的运行线索,当从一个线
   程切换到另一个线程上时,必须将原有的线程的寄存器集合的状态保存,以便
   将来该线程在被重新切换到时能得以恢复。
 
    3.线程的堆栈
       堆栈是保证线程独立运行所必须的。
       线程函数可以调用函数,而被调用函数中又是可以层层嵌套的,所以线程
   必须拥有自己的函数堆栈,使得函数调用可以正常执行,不受其他线程的影
   响。

    4.错误返回码
       由于同一个进程中有很多个线程在同时运行,可能某个线程进行系统调用
   后设置了errno值,而在该线程还没有处理这个错误,另外一个线程就在此时
   被调度器投入运行,这样错误值就有可能被修改。
       所以,不同的线程应该拥有自己的错误返回码变量。

    5.线程的信号屏蔽码
       由于每个线程所感兴趣的信号不同,所以线程的信号屏蔽码应该由线程自
   己管理。但所有的线程都共享同样的信号处理器。

    6.线程的优先级
       由于线程需要像进程那样能够被调度,那么就必须要有可供调度使用的参

   数,这个参数就是线程的优先级。

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

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

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

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

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

  这个问题是笔者在公司实习的时候发现的,因为当时刚刚涉及多线程程序设计,操作系统中如此简单的话题困扰笔者很久,希望可以对初涉C++多线程的读者 有所帮助! 2)如果两个线程共享堆,而且都有可能执行内存分配和释放操作,就必须进行同步保护,这个和C类,R类,T类没有关系。你看到的例子两个线程应该是使用各 自的堆。 

  在 windows 等平台上,不同线程缺省使用同一个堆,所以用 C 的 malloc (或者 windows 的 GlobalAlloc)分配内存的时候是使用了同步保护的。如果没有同步保护,在两个线程同时执行内存操作的时候会产生竞争条件,可能导致堆内内存管理 混乱。比如两个线程分配了统一块内存地址,空闲链表指针错误等。 

  Symbian 的线程一般使用独立的堆空间。这样每个线程可以直接在自己的堆里分配和释放,可以减少同步所引入的开销。当线程退出的时候,系统直接回收线程的堆空间,线程内没有释放的内存空间也不会造成进程内的内存泄漏。 

  但是两个线程使用共用堆的时候,就必须用 critical section 或者 mutex 进行同步保护。否则程序崩溃是早晚的事。如果你的线程需要在共用堆上无规则的分配和释放任何数量和类型的对象,可以定制一个自己的 allcator,在 allocator 内部使用同步保护。线程直接使用这个 allocator 分配内存就可以了。这相当于实现自己的 malloc,free。但是更建议你重新审查一下自己的系统,因为这种情况大多数是不必要的。经过良好的设计,线程的本地堆应该能够满足大多数对象的需 求。如果有某一类对象需要在共享堆上创建和共享,这种需求是比较合理的,可以在这个类的 new 和 delete 上实现共享保护。

转载于:https://www.cnblogs.com/jiu0821/p/5870900.html

相关文章:

  • Code[VS] 1022 覆盖 题解
  • Q: ossfs挂载时如何设置权限?
  • 拷贝(复制)构造函数和赋值函数
  • MFC静态分割后锁定分隔条/限制分隔条的移动范围 方法1
  • 异常 ORA-00257: archiver error. Connect internal only, until freed
  • 判断32位整数二进制中1的个数的算法
  • json化 datatable
  • 乐视云视频 接口开发 结合百度编辑器
  • css 布局
  • code异常处理
  • 直线方程公式
  • python中的tab补全功能添加
  • 一个失败团队的养成
  • 利用CSS3 clip-path裁剪各种图形。
  • [BZOJ4016][FJOI2014]最短路径树问题
  • [iOS]Core Data浅析一 -- 启用Core Data
  • Android Volley源码解析
  • classpath对获取配置文件的影响
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • js作用域和this的理解
  • Python利用正则抓取网页内容保存到本地
  • REST架构的思考
  • scala基础语法(二)
  • vue--为什么data属性必须是一个函数
  • 多线程事务回滚
  • 分享一份非常强势的Android面试题
  • 关于字符编码你应该知道的事情
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 如何合理的规划jvm性能调优
  • 实战|智能家居行业移动应用性能分析
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • postgresql行列转换函数
  • 国内开源镜像站点
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ​如何在iOS手机上查看应用日志
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • (26)4.7 字符函数和字符串函数
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (libusb) usb口自动刷新
  • (WSI分类)WSI分类文献小综述 2024
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)Linux下编译安装log4cxx
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .net操作Excel出错解决
  • .NET导入Excel数据
  • [AutoSar]BSW_OS 01 priority ceiling protocol(PCP)