精华内容
下载资源
问答
  • 进程中的线程究竟共享哪些资源,这些你真的了解了吗。
    千次阅读
    2020-07-31 10:55:52

    进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 


    线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 


    一个线程可以创建和撤销另一个线程;     同一个进程中的多个线程之间可以并发执行.

     

    进程在执行过程中拥有独立的内存单元,而该进程的多个线程共享内存,从而极大地提高了程序的运行效率。 
    每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 


    从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

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


    一个进程中的所有线程共享该进程的地址空间,但它们有各自独立的(/私有的)栈(stack),Windows线程的缺省堆栈大小为1M。堆(heap)的分配与栈有所不同,一般是一个进程有一个C运行时堆,这个堆为本进程中所有线程共享,windows进程还有所谓进程默认堆,用户也可以创建自己的堆。 
    用操作系统术语,线程切换的时候实际上切换的是一个可以称之为线程控制块的结构(TCB?),里面保存所有将来用于恢复线程环境必须的信息,包括所有必须保存的寄存器集,线程的状态等。

     

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

     

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

     

     

    进程简说:

    进程就是程序的一次执行。

    进程是为了在CPU上实现多道编程而发明的一个概念。

    事实上我们说线程是进程里面的一个执行上下文,或者执行序列,显然一个进程可以同时拥有多个执行序列,更加详细的描述是,舞台上有多个演员同时出场,而这些演员和舞台就构成了一出戏,类比进程和线程,每个演员是一个线程,舞台是地址空间,这个同一个地址空间里面的所有线程就构成了进程。

    比如当我们打开一个word程序,其实已经同时开启了多个线程,这些线程一个负责显示,一个接受输入,一个定时进行存盘,这些线程一起运转让我们感到我们的输入和屏幕显示同时发生,而不用键入一些字符等好长时间才能显示到屏幕上。

    线程管理:

    将线程共有的信息存放在进程控制块中,将线程独有的信息存放在线程控制块中。

    那么如何区分哪些信息是共享的?哪些信息是独享的呢?

    一般的评价标准是:如果某些资源不独享会导致线程运行错误,则该资源就由每个线程独享,而其他资源都由进程里面的所有线程共享。

    线程共享资源

    线程独享资源

    地址空间

    程序计数器

    全局变量

    寄存器

    打开的文件

    子进程

    状态字

    闹铃

     

    信号及信号服务程序

     

    记账信息

     

    一般情况下进程共享资源与独享资源的划分

    那么对于进程及线程的实现做如何解释呢?

    首先应该明白进程的调度,创建等实质上都是由操作系统实现的,所以说进程的实现只能由操作系统内核来实现,而不存在用户态实现的情况。但是对于线程就不同了,线程的管理者可以是用户也可以是操作系统本身,线程是进程内部的东西,当然存在由进程直接管理线程的可能性。因此线程的实现就应该分为内核态线程实现和用户态线程实现。

    ================================================================================================================

     

    内核态线程实现:

           线程是进程的不同执行序列,也就是说线程是独立运行的基本单位,也是CPU调度的基本单位。

    那么操作系统是如何实现管理线程的呢?

           首先操作系统向管理进程一样,应该保持维护线程的所有资源,将线程控制块存放在操作系统的内核空间中。那么此时操作系统就同时掌管进程控制块和线程控制块。

     

    操作系统管理线程的好处是:

    1.用户编程简单;

    2.如果一个线程执行阻塞操作,操作系统可以从容的调度另外一个线程的执行。

     

    内核线程的实现缺点是:

    1.效率低,因为线程在内核态实现,每次线程切换都需要陷入到内核,由操作系统来调度,而有用户态切换到内核态是要话费很多时间的,另外内核态实现会占用内核稀有的资源,因为操作系统要维护线程列表,操作系统所占内核空间一旦装载后就无法动态改变,并且线程的数量远远大于进程的数量,随着线程数的增加内核将耗尽;

    2.内核态的实现需要修改操作系统,这个是谁都不想要做的事情;

     

    ====================================================================================================================

    那么用户态是如何实现管理线程的呢?

    用户态管理线程就是用户自己做线程的切换,自己管理线程的信息,操作系统无需知道线程的存在。

    在用户态下进行线程的管理需要用户创建一个调度线程。一个线程在执行完一段时间后主动把资源释放给其他线程使用,而在内核台下则无需如此,因为操作系统可通过周期性的时钟中断把控制权夺过来,在用户态实现情况下,执行系统的调度器也是线程,没有能力夺取控制权。

     

    用户态实现有什么优点?

     首先是灵活,因为操作系统不用知道线程的存在,所以任何操作系统上都能应用;

    其次,线程切换快,因为切换在用户态进行,无需陷入带内核态;

    再次,不用修改操作系统实现容易。

     

    用户态实现的缺点呢?

           首先编程起来很诡异,由于在用户台下各个进程间需要相互合作才能正常运转。那么在编程时必须考虑什么情况下让出CPU,让其他的线程运行,而让出时机的选择对线程的效率和可靠性有很大影响,这个并不容易做到;

           其次,用户态线程实现无法完全达到线程提出所要达到的目的:进程级多道编程;,如果在执行过程中一个线程受阻,它将无法将控制权交出来,这样整个进程都无法推进。操作系统随即把CPU控制权交给另外一个进程。这样,一个线程受阻造成整个进程受阻,我们期望的通过线程对进程实施分身的计划就失败了。这是用户态线程致命的缺点。

           调度器激活:线程阻塞后,CPU控制权交给了操作系统,要激活受阻进程的线程,唯一的办法就是让操作系统在进程切换时先不切换,而是通知受阻的进程执行系统(即调用执行系统),并问其是否还有别的线程可以执行。如果有,将CPU控制权交给该受阻进程的执行系统线程,从而调度另一个可以执行的线程到CPU上。一个进程挂起后,操作系统并不立即切换到别的进程上,而是给该进程二次机会,让其继续执行。如果该进程只有一个线程,或者其所有线程都已经阻塞,则控制权将再次返回给操作系统。而现在,操作系统就会切换到其他线程了。

    =============================================================================================================================

     

    现在操作系统的线程实现模型:

    鉴于用户态与内核态都存在缺陷,现代操作将两者结合起来。用户态的执行负责进程内部线程在非阻塞时的切换;内核态的操作系统负责阻塞线程的切换,即我们同时实现内核态和用户态线程管理。每个内核态线程可以服务一个或者更多个用户态线程。

     

    线程从用户态切换到内核态:

    什么情况下会造成线程从用户态到内核态的切换呢?

    首先,如果在程序运行过程中发生中断或者异常,系统将自动切换到内核态来运行中断或异常处理机制。

    此外,程序进行系统调用也会从用户态切换到内核态。

    更多相关内容
  • 提出一种重命名寄存器配对共享分配策略,在运行N个独立线程的结构中,将重命名寄存器分成N份,每个主动线程及其相应的冗余线程共享其中的一份,这样就可以比较有效地缓解竞争式共享所带来的负面影响.实验表明,配对共享...
  • 最近在看Go语言的goroutine调度,看到一篇理论文章,对一些关于Linux多线程的知识进行进一步的了解并且记录。 目录 什么是:CPU寄存器 CPU上下文切换? 进程上下文切换 线程上下文切换 中断上下文切换 Go程序...

    最近在看Go语言的goroutine调度,看到一篇理论文章,对一些关于Linux多线程的知识进行进一步的了解并且记录。

    目录

    什么是:CPU寄存器 CPU上下文切换?

    进程上下文切换

    线程上下文切换

    中断上下文切换

    Go程序内核线程能有多少个?

    Linux创建的线程是用户级还是内核级线程?


    什么是:CPU寄存器 CPU上下文切换?

    CPU寄存器,是CPU内置的容量小、但速度极快的内存

    在说上下文切换的前,需要知道

    程序计数器(Program Counter,PC),则是用来存储CPU正在执行的指令的位置,或者即将执行的下一条指令的位置。他们(CPU寄存器和程序计数器)都是CPU在运行任何任务前,必须依赖的环境,因此也被叫做CPU上下文。

    CPU上下文切换,就是先把前一个任务的CPU上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文,到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。而保存下来的上下文,会存储在系统内核中,并在任务重新调度执行的时候再加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。

    CPU上下文切换分为三种:

    1. 进程上下文切换
    2. 线程上下文切换
    3. 中断上下文切换

    进程上下文切换

    Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中。CPU特权等级的Ring0 和 Ring3(也就是说Ring0和Ring3程序可以在CPU上运行)。

    1. 内核空间(Ring 0)具有最高权限,可以直接访问所有资源。
    2. 用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。

    换个角度看,也就是说,进程即可以在用户空间运行,又可以在内核空间中运行。进程在用户空间运行是,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。

    从用户态到内核态的转变,需要通过系统调用来完成,比如当我们查看文件内容时,就需要多次系统调用来完成:首先调用open()打开文件,然后调用read()读取文件内容,并调用write()将内容写到标准输出,最后再调用close()关闭文件。

    • 那么,系统调用的过程有没有发生CPU上下文切换呢?答案是肯定的。

    CPU寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。而系统调用结束后,CPU寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程,所以一次系统调用的过程,其实是发生了两次CPU上下文切换。

    不过,需要注意的是,系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程。这跟我们通常所说的进程上下文切换是不一样的。进程上下文切换,是指从一个进程切换到另一个进程运行;而系统调用过程中一直是同一个进程在运行。

    所以,系统调用过程通常称为特权模式切换而不是上下文切换。但实际上系统调用过程中,CPU的上下文切换还是无法避免的。

    • 那么,进程上下文切换跟系统调用又有什么区别呢?

    首先,进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以进程的上下文不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包含了内核堆栈、寄存器等内核空间状态。

    因此,进程的上下文切换就比系统调用多了一步:在保存当前进程的内核状态和CPU寄存器之前,需要先把该进程的虚拟内存、栈等用户态资源保存下来;而加载了下一进程的内核态后,还需要刷新新进程的虚拟内存和用户栈。如下图所示,保存上下文和恢复上下文的过程,并不是免费的,需要内核在CPU上允许才能完成。

    根据Tsuna的测试报告,每次上下文切换都需要几十纳秒到数微妙的CPU时间。这个时间还是相当可观的,特别是进程上下文切换次数较多的情况下,很容易导致CPU将大量的时间耗费在寄存器、内核栈、以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间。

    另外,我们知道,Linux通过TLB(Translation Lookaside Buffer)来管理虚拟内存到物理内存的映射关系。当虚拟内存更新后,TLB也需要刷新,内存的访问也会随之变慢。特别是在多处理器系统上,缓存是被多个处理器共享的,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程。

    • 知道了进程上下文切换潜在的性能问题后,我们再来看,究竟什么时候会切换进程上下文?

    显然,进程切换时才需要切换上下文,换句话说,只有在进程调度的时候,才需要切换上下文。Linux为每个CPU都维护了一个就绪队列,将获取进程(即正在运行和等待CPU的进程)按照优先级和等待CPU的时间排序,然后选择最需要CPU的进程,也就是优先级最高和等待CPU时间最长的进程来运行。

    • 那么,进程在什么时候才会被调度到CPU上运行呢?

    最容易想到的一个时机,就是进程执行完,终止了,它之前使用的CPU会释放出来,这个时候再从就绪队列里,拿一个新的进程过来运行。其实还有很多其他场景,也会触发进程调度,这里逐个梳理下。

    1. 为了保证所有进程可以得到公平调度,CPU时间片被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样,当某个进程的时间片耗尽了,就会被系统挂起,切换到其他正在等待CPU的进程运行。
    2. 进程在系统资源不足(比如内存不足)时,需要等到资源满足后才可以运行,这个时候进程也会被挂起,并由系统调度其他进程运行。
    3. 当进程通过睡眠函数sleep这样的方法将自己主动挂起时,自然也会重新调度。
    4. 当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级的进程来运行。
    5. 当发生硬件中断时,CPU上的进程会被中断挂起,转而执行内核中中断服务程序。

    线程上下文切换

    线程与进程最大的区别在与,线程是调度的基本单位,而进程则是资源拥有的基本单位。所谓内核中的任务调用,实际上的调度对象是线程;而进程只是给线程提供了虚拟内存、全局变量等资源。所以,对于线程和进程,我们可以这么理解:

    • 当进程只有一个线程时,可以认为进程就等于线程。
    • 当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。
    • 线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保存的。

    这么一来,线程的上下文切换其实就可以分为两种情况:

    1. 前后两个线程属于不同进程,此时,由于资源不共享,所以切换过程就跟进程上下文切换是一样的。
    2. 前后两个线程属于同一个进程,此时,应为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据,寄存器等不共享的数据。

    所以同为上下文切换,但同进程内的线程切换,要比多进程间切换消耗更少的资源,这也正是多线程代替多进程的一个优势。

    中断上下文切换

    为了快速响应硬件的时间,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备时间。而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行。

    因为中断这块一般都不会涉及,所以不做过多介绍。

     

    Go程序内核线程能有多少个?

    其实这个是简单的问题(上面已经间接回答了),在没有看goroutine的MPG调度模型前,我肯定知道,理论上会有N个内核线程;但是看完后,总是模模糊糊的,以为会和CPU个数有关系,其实没有关系,M(即内核线程)是按需创建的,但是如果只有一个cpu(1核)同一时刻只能执行一个内核线程。(这也算是个误区,很多人认为runtime.GOMAXPROCS可以限制系统线程的数量)

    虽然M理论上可以有N(但是N<maxcount)个,但是很多以后会有一个问题就是,频繁CPU上下文切换,倒是大多时间都消耗在CPU上下文切换。

     

    Linux创建的线程是用户级还是内核级线程

    你可能知道:线程分为内核态线程和用户态线程,用户态线程需要绑定内核态线程,CPU并不能感知用户态线程的存在,它只知道它在运行1个线程,这个线程实际是内核态线程。

    线程的实现曾有3种模型:

    1. 多对一(M:1)的用户级线程模型
    2. 一对一(1:1)的内核级线程模型
    3. 多对多(M:N)的两级线程模型

    上面的x对y(x:y)即x个用户态线程对应y个内核调度实体(Kernel Scheduling Entity,这个是内核分配CPU的对象单位)。

    多对一用户线级程模型  

    多对一线程模型中,线程的创建、调度、同步的所有细节全部由进程的用户空间线程库来处理。用户态线程的很多操作对内核来说都是透明的,因为不需要内核来接管,这意味不需要内核态和用户态频繁切换。线程的创建、调度、同步处理速度非常快。当然线程的一些其他操作还是要经过内核,如IO读写。这样导致了一个问题:当多线程并发执行时,如果其中一个线程执行IO操作时,内核接管这个操作,如果IO阻塞,用户态的其他线程都会被阻塞,因为这些线程都对应同一个内核调度实体。在多处理器机器上,内核不知道用户态有这些线程,无法把它们调度到其他处理器,也无法通过优先级来调度。这对线程的使用是没有意义的!

    一对一内核极线程模型 

    一对一模型中,每个用户线程都对应各自的内核调度实体。内核会对每个线程进行调度,可以调度到其他处理器上面。当然由内核来调度的结果就是:线程的每次操作会在用户态和内核态切换。另外,内核为每个线程都映射调度实体,如果系统出现大量线程,会对系统性能有影响。但该模型的实用性还是高于多对一的线程模型。

    多对多两极线程模型   

    多对多模型中,结合了1:1和M:1的优点,避免了它们的缺点。每个线程可以拥有多个调度实体,也可以多个线程对应一个调度实体。听起来好像非常完美,但线程的调度需要由内核态和用户态一起来实现。可想而知,多个对象操作一个东西时,肯定要一些其他的同步机制。用户态和内核态的分工合作导致实现该模型非常复杂。linux多线程模型曾经也想使用该模型,但它太复杂,要对内核进行大范围改动,所以还是采用了一对一的模型!!!

     

    那么,Linux下C语言thread_create函数创建的线程属于用户级还是内核级。其实创建的还是用户级线程,只不过对应了一个内核级的内核调度线程(这个线程实际的内核调度器分配的),即一对一(1:1)的内核级线程模型。

    Go语言中goroutine使用就是一种特殊的两级线程模型(MPG模型)。得益于这种模型,所以Go语言并发性比其他语言都要好。


    参考原文:

    CPU上下文切换是什么

    Linux历史上线程的3种实现模型 

    Go并发原理

    展开全文
  • 进程有哪些资源? 线程包含哪些?

    哪些是线程私有的?

    线程实际上一个个函数的执行过程,函数执行过程中的信息保存在栈帧中,一个个栈帧构成栈区,程序执行过程中需要寄存器来存中间变量,还需要一个程序计数器,指向下一条执行的指令;线程所属栈区、程序计数器以及函数运行时所需的寄存器是线程私有的,称为线程上下文 thread context。

    哪些是线程共享的?

    堆区

    Java 程序中 new 出来的对象就放在这里,只要有该对象的指针,其他线程也可以访问该对象。(Java中的引用传递就是传递对象的引用,而简单数据类型在栈区分配,只能值传递)

    已打开的文件

    线程打开的文件资源是挂在进程上的,线程销毁后文件资源不会自动回收,这就是为什么打开的文件要及时关闭的原因。

    动态链接库

    源代码编译为目标代码后需要经过链接才能成为可执行文件(Windows中的exe文件,Linux中的ELF文件),链接时有动态链接和静态链接,静态链接就是将所有机器指令全部打包到可执行文件中,动态链接则是在运行时再找动态库中的机器指令。这些动态链接库是线程共享的。

    代码区

    代码区存放的是机器指令,源代码编译后成为的机器指令就放在这里,所有的线程共享代码区,也就是说没有特定的函数只能被某个线程执行。

    数据区

    数据区中方的是全局变量,Java中static修饰的变量就放在这里。

     

    展开全文
  • 线程、数据计数器线程线程的内存空间JVM 线程PC 寄存器PC 寄存器的作用 线程 **每个JVM都有Runtime类,且只有一个Runtime实例。**即为运行时环境,相当...灰色的为单独线程私有的,红色的为多个线程共享的: 1. 线程

    线程

    请添加图片描述
    请添加图片描述
    每个JVM都有Runtime类,且只有一个Runtime实例。即为运行时环境,相当于内存结构的中间的那个框:运行时环境。
    请添加图片描述

    线程的内存空间

    Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区:

    1. 其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。
    2. 另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。

    灰色的为单独线程私有的,红色的为多个线程共享的
    1. 线程独有:程序计数器、虚拟机栈栈、本地方法栈
    2. 线程间共享:堆、方法区

    如果一个进程中有5个线程,意味着有5组程序计数器、本地方法栈、虚拟机栈,这5个线程公用方法区和堆。
    请添加图片描述

    JVM 线程

    1. 线程是一个程序里的运行单元。JVM允许一个应用有多个线程并行的执行
    2. 在Hotspot JVM里,每个线程都与操作系统的本地线程直接映射

    3. 当一个Java线程准备好执行以后,此时一个操作系统的本地线程也同时创建。Java线程执行终止后,本地线程也会回收
    4. 操作系统负责将线程安排调度到任何一个可用的CPU上。一旦本地线程初始化成功,它就会调用Java线程中的run()方法
    5. 如果一个线程抛异常,并且该线程是进程中最后一个守护线程,那么进程将停止

    程序计数器(PC寄存器,Program Counter Register)

    请添加图片描述
    1、它是一块很小的内存空间,几乎可以忽略不记,也是运行速度最快的存储区域。
    2、在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。
    3、任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;

    如果是在执行native方法,则是未指定值(undefined)。
    4、它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
    5、它是唯一一个在Java虚拟机规范中没有规定任何OutofMemoryError情况的区域。

    PC 寄存器(程序计数器)的作用

    PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令,并执行该指令。
    类似于遍历数据库结果集的游标,不停的指向下一条。
    请添加图片描述
    在虚拟机栈中,每一个栈帧里封装着局部变量表、操作数栈、动态链接、方法返回值。方法调用时会压栈,调用结束后出栈然后回到上一个(之前代码)执行的地方继续执行,类似于递归。

    int i = 3;
    int j = 5;
    int sum = i + j;
    

    在这里插入图片描述
    请添加图片描述
    对于栈来说没有垃圾回收,只有入栈和出栈。
    栈存在溢出问题,StackoverflowError 栈溢出,但是栈的大小可以改变,默认1M(1兆)。
    线程过多可能会导致 OutofMemoryError 内存溢出,因为每个线程中都有一份程序计数器、本地方法栈、虚拟机栈。

    PC寄存器(程序计数器)为什么被设定为私有的?

    所谓的多线程在一个特定的时间段内只会执行其中某一个线程的方法,CPU会不停地做任务切换,这样必然导致经常中断或恢复,为了能够准确地记录各个线程正在执行的当前字节码指令地址,最好的办法自然是为每一个线程都分配一个PC寄存器,这样一来各个线程之间便可以进行独立计算,从而不会出现相互干扰的情况。

    请添加图片描述

    CPU 时间片

    CPU时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片。
    在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。
    但在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。

    展开全文
  • 假设单核CPU的情况下。(既高速缓存都是一样的) 一 一个变量a被线程A和线程B...还是这个例子,假设A线程和B线程共享主存数据a变量,A、B线程读入到CPU缓存后,到底是一个缓存呢?还是各自线程看到的缓存是不一样的?
  • 根据他,两个线程不一定共享静态变量,特别是在每个线程(主线程对ReaderThread)在其自己的处理器上运行并且因此不共享相同的寄存器/高速缓存等等的情况下, CPU不会更新其他。基本上,他说可能是ready在主线程更新,...
  • 缓存 内存 寄存器 共享内存 首先,寄存器的速度大于缓存的速度大于内存的速度。 缓存是由于CPU重复地从内存的同一地址取出数据,这样的操作可被缓存代替。 一级缓存相较于二级三级缓存 容量最小,速度最快。 寄存器...
  • 为了降低寄存器压力,可以使用更多的每线程本地存储器或每个线程共享存储器 . CUDA nvcc编译器也可以强制每个线程使用更少的寄存器 . 该方法对于具有良好算术延迟的工作负载是有用的,即ALU操作与存储器r / w访问...
  • 线程概念:线程的独有和共享

    千次阅读 2021-10-12 13:12:53
    线程概念: 在Linux内核中,实质上是没有线程这个概念的,也没有提供创建线程的接口; 创建线程的接口,是通过库函数实现的,为了让pcb可以实现只调度完整代码中的某一或部分函数。 可以理解为:进程是一个pcb集合,...
  • 这也是为什么我把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域...
  • 同一进程的线程共享的资源和独有的资源
  • 进程是资源分配的基本单位;线程是系统调度的基本单位。...同一进程间的线程究竟共享哪些资源呢,而又各自独享哪些资源呢? 共享的资源有 a. 堆 由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;因此n
  • jvm中堆栈的数据共享和线程共享

    千次阅读 多人点赞 2018-09-06 12:57:33
    起初,我一直不清楚到底是堆共享还是栈共享,后来查阅了很多资料,有说是堆共享,又有说栈共享,直到最后我才了解到共享分为两个:一个为数据共享,一个为线程共享。 先来分析数据共享: int a = 3; int b = 3; ...
  • 同一进程下线程共享的数据和独有的数据
  • 线程共享进程数据,但是也拥有自己一部分数据 独有:栈 , 寄存器(上下文信息),调度优先级,信号屏蔽字,标识符 共享:虚拟地址空间(代码段、数据段),文件描述符,信号处理方式,工作路径,用户组ID/组ID .....
  • 每个线程都有对应的函数栈,栈帧里面包含了有局部变量、参数、返回的参数、返回的地址、寄存器信息等 2、调度信息 线程需要被操作系统调度 3、程序计数器和寄存器的状态 用来标志着当前执行代码的位置 4、栈的指针 ...
  • ➡PC寄存器(Program Counter Register)即程序计数器 ⭐存放的是指令在内存中的地址 ????寄存器是CPU内部用来存放数据的一些小型存储区域 PC寄存器中的地址默认是自动加1的 ❓PC中的初始值? 内存中的指令是从...
  • 线程中的使用共享变量的问题

    千次阅读 2021-05-20 19:17:33
    一组并发线程运行在一个进程的上下文中,每个线程都有它自己独立的线程上下文,例如:栈、程序计数器、线程ID、条件码等,每个线程和其它的线程一起共享除此之外的进程上下文的剩余部分,包括整个用户的虚拟地址空间...
  • 线程之间是否共享静态变量?

    千次阅读 2021-03-06 05:04:51
    根据他的说法,两个线程不一定共享静态变量,特别是在每个线程(主线程与ReaderThread)在其自己的处理器上运行并因此不共享相同的寄存器/缓存/等的情况下CPU不会更新另一个。基本上,他说有可能ready在主线程中更新,...
  • 线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。 进程拥有这...
  • 线程之间共享的内容

    千次阅读 2016-08-02 23:18:41
    在一个进程的线程共享堆区,而进程中的线程各自维持自己堆栈。 线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程...
  • 线程间到底共享了哪些进程资源?

    千次阅读 2020-12-15 21:20:00
    点击上方IT牧场,选择置顶或者星标技术干货每日送达进程和线程这两个话题是程序员绕不开的,操作系统提供的这两个抽象概念实在是太重要了。关于进程和线程有一个极其经典的问题,那就是进程和...
  • 线程之间共享与独享的资源 进程是资源分配的基本单位;线程是系统调度的基本单位。 平时我们写的程序都是作为线程运行的;进程可以看做是包括一系列线程和资源的统称;一个进程至少包括一个 线程(主线程,进入main...
  • 同一个进程下的线程共享哪些资源

    千次阅读 2015-10-19 21:04:36
    线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。    进程拥有这许多共性...
  • CUDA:寄存器详解

    千次阅读 2018-05-21 10:46:15
    为了运行一个新任务,CPU需要进行上下文切换,将当前所有寄存器的状态保存到栈上,然后从栈中恢复当前需要执行的新线程上次的执行状态。这些操作需要花费上百个CPU时钟周期。如果在CPU上开启过多...
  • 一、同一进程间的线程共享内存地址空间,其中进程用户空间的五个段 英文: .bss 、.data 、 .text 、 stack 、heap 。 中文:BSS段(bss segment),数据段:数据段(data segment),代码段:代码段(code segme...
  • Linux线程的实质

    2021-02-23 23:21:56
    线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.一个线程可以创建和撤销另一个线程;同一个进程中的多...
  • 线程私有与共享

    千次阅读 2018-05-22 21:09:53
    线程私有:栈(局部变量,函数的参数)线程局部存储(Thread Local Storage,TLS)。有限的容量寄存器 (执行流的基本数据)TLS的用法很简单,如果要定义一个全局变量为TLS类型,只需在她定义前加上相应的关键字即可...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 93,532
精华内容 37,412
关键字:

寄存器是线程共享的吗