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

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

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

进程在执行过程中拥有独立的内存单元,而该进程的多个线程共享内存,从而极大地提高了程序的运行效率。

每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

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

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

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

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

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

进程简说:

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

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

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

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

线程管理:

线程共有的信息存放在进程控制块中(PCB),将线程独有的信息存放在线程控制块中(TCB)

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

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

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

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

[内核态线程实现]:

线程是进程的不同执行序列,也就是说线程是独立运行的基本单位,也是CPU调度的基本单位。那么操作系统是如何实现管理线程的呢?

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

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

1.用户编程简单;

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

内核线程的实现缺点是:

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

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

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

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

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

用户态实现有什么优点?

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

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

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

用户态实现的缺点呢?

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

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

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

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

用户态的执行负责进程内部线程在非阻塞时,即我们同时实现内核态和用户态线程管理。每个内核态线程可以服务一个或者更多个用户态线程。

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

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

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

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

转自:https://www.cnblogs.com/baoendemao/p/3804677.html

【Linux 线程】同一个进程中的线程共享哪些资源的更多相关文章

  1. 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

    一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...

  2. 查看JAVA进程中哪个线程CPU消耗最高

    一,在centos linux 上查看进程占用cpu过高 top  shift+h 查看哪个进程程消耗最高     二,查看JAVA进程中哪个线程消耗最高   2.1 导出java运行的线程信息   ...

  3. 分析占用了大量 CPU 处理时间的是Java 进程中哪个线程

    下面是详细步骤: 1. 首先确定进程的 ID ,可以使用 jps -v 或者 top 命令直接查看 2. 查看该进程中哪个线程占用大量 CPU,执行 top -H -p [PID] 结果如下: 可以发 ...

  4. 分析占用了大量CPU处理时间的是Java进程中哪个线程

    下面是详细步骤: 1. 首先确定进程的 ID ,可以使用 jps -v 或者 top 命令直接查看 2. 查看该进程中哪个线程占用大量 CPU,执行 top -H -p [PID] 结果如下: 可以发 ...

  5. Activity和Service是否是在同一个进程中运行。

    一般情况下,Activity和Service在同一个包名内,并且没有设定属性android:process=":remote",两者在同一个进程中. 因为一个进程只有一个UI线程, ...

  6. android中activity和service是否在同一个进程中

    分两种情况,如果是本地线程,肯定是同一个进程中的, 如果是远程服务,那么activity和service将在不同的进程中的 ----- 非远程服务,和Activity属于同一个进程和线程:而远程服务和 ...

  7. 00014 - linux中用top、ps命令查看进程中的线程

    在Linux上显示某个进程的线程的几种方式. 方法一:PS 在ps命令中,“-T”选项可以开启线程查看.下面的命令列出了由进程号为<pid>的进程创建的所有线程. 1.$ ps -T -p ...

  8. python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用)

    一:自定义线程池的实现 前戏: 在进行自定义线程池前,先了解下Queue队列 队列中可以存放基础数据类型,也可以存放类,对象等特殊数据类型 from queue import Queue class ...

  9. Python 开启线程的2中方式,线程VS进程(守护线程、互斥锁)

    知识点一: 进程:资源单位 线程:才是CPU的执行单位 进程的运行: 开一个进程就意味着开一个内存空间,存数据用,产生的数据往里面丢 线程的运行: 代码的运行过程就相当于运行了一个线程 辅助理解:一座 ...

随机推荐

  1. NSMapTable

    跟NSDictionary用法差不多,不过区别是NSMapTable可以设置内存选项,例如可以设置key跟value的内存属性(weak/strong),从而避免内存泄露. 例如这个+ weakToW ...

  2. 1:python 简介与基础

    什么是python? 1.python是一种面向对象的解释型语言,它继承了传统编译语言的通用性和强大性,同时也借鉴了简单脚本和解释语言的易用性. 2.python 在自动化测试.人工智能.数据分析等方 ...

  3. Cookie安全小结

    Cookie机制:一般来说,同域内浏览器中发出的任何一个请求都会带上Cookie,无论请求什么资源,请求时,Cookie出现在请求头的Cookie字段中.服务端响应头的Set-Cookie字段可以添加 ...

  4. 用crash来分析一下proc的文件访问

    一般来说,用户通过fd的传入,调用open系统调用,来获取fd,然后read的时候,通过这个fd来查找对应的file* SYSCALL_DEFINE3(open, const char __user ...

  5. CentOS 6.x 默认源中带了mysql-server,可以使用yum安装。

    1.执行安装命令:yum install mysql-server 2.初始化数据库,使用命令1# service mysqld start   启动MSQL service mysqld stop  ...

  6. week06 09 NodeJS Server as a RPCclient - jayson

    nodeserver端的rpcclient 来调用后端backendserver端定义的add等方法 2个server连通 Make NodeJs as a client - Npm jayson 用 ...

  7. func 的参数修饰

    1.0 在声明一个 Swift的方法的时候,我们一般不去指定参数前面的修饰符,而是直接声明参数: func incrementor(variable : Int) ->Int { } 这个方法接 ...

  8. android listview中item通过viewpager实现《IT蓝豹》

    android listview中item通过viewpager实现 android listview中item通过viewpager实现,每一个item都支持viewpager实现图片切换功能.本项 ...

  9. Hadoop集群(三) Hbase搭建

    前面已经完成Zookeeper和HDFS的安装,本文会详细介绍Hbase的安装步骤.以及安装过程中遇到问题的汇总. 系列文章:   Hadoop集群(一) Zookeeper搭建 Hadoop集群(二 ...

  10. jQuery之dom操作(取赋值方法)

    取赋值相关方法:                   .html() .text() .size()                   .addClass() .removeClass() .has ...