终于有人把进程与线程讲清楚了

很多人对进程,线程没有什么概念,或者面试的时候说不出里面的核心内涵,今天我打算花一点篇 幅把进程和线程讲清楚。

这里有个游戏开发学习小组点击可以直接加入,一起学习交流吧

1: CPU与内存

CPU 大家都知道是计算机的中央运算单元,用来计算的。CPU从内存里面读取一条一条的代码指令,然后根据指令来执行运算(加,减,乘,除,复制数据等)。 CPU在运算的过程中一些数据存放在CPU的寄存器和内存里面, CPU里面有各种寄存器,各司其职。指令指针寄存器存放的是当前执行到那条代码指令了。代码指令是写完程序后被编译器编译成二进制指令代码

2: 内核与虚拟内存。

电脑或手机开机以后,上电跑启动代码,运行OS内核,内核里也有线程,这个我们把它叫做内核态。内核启动以后, 内核将物理内存管理起来。内核提供虚拟内存管理机制给每个进程(应用程序App)内存服务。它的思路是什么呢?每个进程(应用App) 都有自己的虚拟内存空间,注意这里的空间只是一个数字空间,没有划分实际的物理内存。这样做的好处是多个进程(应用App)内存都是独立的相互不影响,物理内存只有一个,多个进程(应用App)不会因为直接使用物理内存而冲突。那么OS是如何管理物理内存的呢?进程(应用App)需要内存的时候,OS分配一块虚拟内存(起点---终点),然后OS在从自己管理的物理内存里面分配出来物理内存页,然后通过一个MMU的单元,将分配的虚拟内存与物理内存页映射起来,这样,读写虚拟内存地址最终通过映射来使用物理内存地址,这样每个进程之间的内存是独立的,安全的。每个进程会把虚拟内存空间分成4个段(代码段, 数据端,堆,栈)

代码段:用来存放进程(应用App)的代码指令。

数据端: 用来存放全局变量的内存。

堆: 调用os的malloc/free 来动态分配的内存。

栈: 用来存放局部变量,函数参数,函数调用与跳转。

每个进程(应用App)相当于一个容器,所有应用App里面需要的资源和机制都在进程里面。线程是OS独立调度执行的单元,OS调度执行的单位就是线程,线程需要以进程作为容器和使用进程相关的环境。

应用态没有进程就不会有线程。

3: 进程与线程

上面说过进程是容器,应用态的线程必须要基于进程来创建出来。那么进程与线程他们之间到底是一个什么样的关系,接下来我们来分析一下。例如"在桌面上双击打开一个App", 桌面App程序会调用OS的系统调用接口fork,让OS 创建一个进程出来, OS为你准备好进程的结构体对象,将这个App的文件(xxx.exe, 存放编译好的代码指令)加载到进程的代码段,同时OS会为你创建一个线程(main thread), 在代码里面,你还可以调用OS的接口,来创建多个线程。这样OS就可以调度这些线程执行了。 虚拟内存空间是进程的概念,那么线程如何使用的呢?各线程使用共享进程的代码段,数据段,堆,每个线程在进程的栈空间创建一个属于自己的栈空间。所以这样就得到一些结论如下:

每个线程共享进程的代码段内存空间,所以我们编写多线程代码的时候,可以在任何线程调用任何函数。

每个线程共享进程的数据段内存空间,所以我们编写多线程代码的时候,可以在任何线程访问全局变量。

每个线程共享进程的堆,所以我们编写多线程代码的时候,可以在一个线程访问另外一个线程new/malloc出来的内存对象。

每个线程都有自己的栈的空间,所以可以独立调用执行函数(参数,局部变量,函数跳转)相互之间不受影响。

4: OS如何调度线程的。

CPU一般会有多个核心,每个核心都调度一个线程执行。CPU有几个核心,最多同时可调度几个线程(多核能让电脑更快就是这个原理)。OS的功能就是要在合适的时候分配CPU核心来调度合适的线程。为了能实现多任务并发,OS不允许一个OS核心长期固定调度一个线程。

OS是如何调度CPU核心来执行各个线程呢? OS会根据线程的优先级分配每次调度最多执行的时间片,这个时间一到,不管怎么样,都要重新调度一次线程(也许还是调度到这个线程,这个不重要)。除了时间片以外,线程会等待某些条件(磁盘读取文件,网卡发送完数据, 线程休眠, 等待用户操作)这样也会把这个线程挂起,OS会重新找一个新的线程继续执行,只到挂起的这个线程的条件满足了,重新把这个线程放到可调度队列里面,这个线程又有机会被OS调度CPU核心来执行。当我们打开电脑的任务管理器,你会发现很多线程的CPU占有率为0%, 说明这些线程都由于某些条件而挂起了。没有被OS调度。

每个线程“随时随地”都可能被OS 中断执行,并调度到其它的线程执行。OS是如何保证一个线程在调度出去后,再重新调度回来能继续之前的数据状态来执行呢?OS是这么做到的。每个线程都会有一个运行时的环境(运行时CPU的每个寄存器的值, 栈独立, 栈的内存数据不会变。数据段,堆共用,可能调度回来会变)。当OS要把某个CPU核心调度出去给其它线程的时候,首先会把当前线程的运行环境(寄存器的值等)保存到内存,然后调度到其它线程,等再次调度回来的时候,再把原来保存到内存的寄存器的值,再设置会CPU核心的寄存器里面,这样就回到了调度出去之前的进度。

调度回来以后,有些会改变,因为多线程之间共用了代码段(代码段只读,不会改),数据段(全局变量调度回来后,可能被其它线程篡改,不是调度之前的那个值了), 堆(调度回来后,动态内存分配的对象内存数据可能被其它线程出篡改),调度回来后,栈上的数据是不变的,因为每个线程都有自己的栈空间。线程调度前后哪些会变,哪些不变你要清楚。这样你写多线程代码的时候才能清晰。

线程调度的开销就是:保存上下文执行环境,内核态运行算法决定接下来调度那个线程,切换这个线程的上下文环境。

5: 线程锁的核心原理是什么?

多线程切换的时候,栈,代码段的数据不会变,数据段与堆的数据切换前后可能会发生改变,这个就造成了"竞争", 如果某些关键数据,在执行代码的时候,不允许这种竞争性的改变,怎么办呢?这个时候多线程就给了一个机制,这个机制就是锁,那么锁的原理是什么?接下来我来和你详细的讲解。

例如: 我编写一个函数,

funcA() {

lock(锁) // 要保护的数据的逻辑部分。

unlock(锁)

}

当线程A调用FuncA(),线程B也调用FUNCA(),OS如何设计锁能保证他们竞争的唯一性的呢?我们把具体过程来分析一下。

假设线程A调用funcA(); 它获取了锁,执行到中间某个代码的时候,时间片用完了,被OS调度出去,OS调度线程B来执行funcA(), 这个时候,当线程B跑到lock(锁)的时候,发现这个锁已经被线程A拿了,这个时候,线程B会主动把自己挂起到锁这个“事件”上(等着锁释放)。OS从新调度线程执行,当重新调度到线程A的时候,线程A执行,执行完成以后,释放掉这个锁,那么线程B又从等待这个锁的队列,到线程调度的就绪队列,又可被OS调度到,等线程A调度出去后,线程B去lock这个锁,就占用了这个锁,然后继续执行。这样就保证了lock/unlock之间的代码永远只有一个线程跑进去了。这样保护了这段代码里面相关的数据和逻辑。

进程与线程各位老铁一定要掌握好,这样你写程序才能做到心中用代码, 今天的分享就到这里了,谢谢再见。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容