比喻

1.线程和进程的关系

一、如果我们单纯把资金作为资源的话,我们可以看出,公司是所有资金的拥有者,恰如进程是所有资源的所有者一样。员工要开展工作,需要和公司申请经费,而线程若想正确执行,也需要有足够的资源(最常见的就是内存)。在资本市场上,公司也可以算是最小运作单元了吧,就像我们认为进程是系统分配内存的最小单元一样。

 

二、一个公司的业务开展,至少需要一个员工的工作,这一情况,恰好类似于一个进程内如果没有线程,则不会发生任何功效。进一步说,事实上,没有任何线程是不可能成功创建出一个进程的,而成立一家没有任何员工的公司貌似也不太可能吧(总有个法人吧)。一个公司显然常常不止一名员工,相应地,很多进程都往往有超过一个的线程。所有线程都执行结束的进程会自然终止,好比所有员工统统离开的公司也必然关张。在日常的工作中,主线程的结束往往会导致整个进程结束而不管其他线程是否在工作状态,相应地,一个公司的老板消失也通常会导致公司直接垮掉,我们这里不妨把老板比喻成主线程。

 

三、有时需要预先准备一组线程来做一类事情,任务到来时找一个相对空闲的线程来执行,这个技术叫做线程池。对应到我们例子中,可以认为这是一个部门。当然,由于线程池中的线程通常是执行相似的/相同的工作,我们这个部门最好是比喻成房产公司的销售部。去过售楼处的肯定都见过,没人的时候,那些穿着性感制服的空闲售楼线程都坐在位置上喝茶嗑瓜子聊天,当有人踏入大门时,就会有一个迎上来执行向你介绍楼盘的工作。如果楼盘销售过于火爆,那制服线程就会出现全忙的现象,客户难免需要排队等待。

 

最后提一下 TLS,这个东西的全名叫线程局部存储(Thread Local Storage)。个人感觉这个很像部门和公司申请的活动经费,实际上是公司的,但却只有本部门可以支配。但这个比喻会打破之前我一直采用的把线程比作单个员工的说法,所以没有正式列入上述正规编制,如果有心思敏捷者,不妨帮助完善此类比系统。


2.多线程的使用为我们的程序提供了众多的方便,同时它也给我们带来了以往没有考虑过的麻烦。当我们使用多线程处理共享资源时意外将会发生:比如我们一起外出就餐,每个人都是一个线程,餐桌上的食物则是共享资源,当我看到红烧鸡腿上桌后立即拿起筷子直奔目标,眼看着就得手的时候,突然~~~鸡腿消失了,一个距离盘子更近的线程正在得意地啃着。 

3.临界区

  打个不是十分妥帖的比喻,就像是有一个仓库资源,但是有多个人想去仓库做点事情。这时候仓库只需要一把锁(锁多了纯粹是浪费^_^),初始状态仓库上的锁是打开的。每个人进去之前先把锁锁住(避免别的人进来),然后自己在仓库里捣弄,离开时再把仓库的锁打开,让别人可以进来。

当我们有一个资源要让多个线程访问的时候,应该创建一个 CRITICAL_SECTION 结构。
一个比喻:一个 CRITICAL_SECTION 结构就像是飞机上的一个卫生间,而马桶则是我们想要保护的数据。由于卫生间很小,因此在同一时刻只允许一个人(线程)在卫生间(关键段)内使用马桶(被保护的资源)。

举个例子相信大家会更明白,路人甲和路人乙要上厕所,刚好找到了一个公共厕所,杯具的是公共厕所里面只有一个位置,路人甲是会员(优先级高),先溜进去了,然后把门锁上(Lock)紧接着里面发出一阵阵巨响....(大家都懂的,最近食物不敢乱吃啊 - -!)。路人乙可着急了,捂着肚子,在外面打转,憋得面红耳赤!过了好一段时间,路人甲抽着香烟,吹着口哨,从厕所里面走出来(Lock解锁了),路人乙急忙钻进去,紧接着又是一阵巨响.....

虽然这个例子举的有点不和谐,但相信大家已经弄明白Lock的作用了。


 

多线程——从生活中理解什么是多线程


   每一个程序可以包含至少一个线程,而多个线程之间可以“并发”执行。

       在介绍线程前先来用生活中最常见的一个小例子来理解什么是线程:

       假如你去一家餐馆吃饭,那家餐馆只有一个服务员,所以这个唯一的服务员给你点菜的时候,别的去餐馆吃饭的人就得等着。但是如果这个餐馆有多个服务员的话,那么在同一时刻就可以给多个去餐馆吃饭的人点菜,这里举A、B两个服务员,分别接待甲、乙两个顾客,而每个顾客点了不同的三道菜。

       上面例子中的餐馆可以理解成一个程序,而A、B两个服务员可以理解成两个线程,后厨做菜的厨师可以看做是CPU(假设只有一个CPU)。

        从A、B两个服务员同时接待甲、乙两个顾客这个表象来看线程是“同步”、“并发”执行的,但是在厨师做菜的过程中还是有先后之分的,只是厨师会把甲乙两个顾客点的菜分开来做,做完甲的一道菜后立刻开始做乙的一道菜,这样不停地切换着做甲乙两个顾客点的菜。而在甲乙顾客看来他们桌上都有着菜吃,误以为他们的菜是同时做出来的。

        而计算机里的多线程也是如此,cpu会分配给每一个线程只有极少的运行时间,时间一到就交出运行权,所有线程被快速的切换执行,因为cpu的执行速度非常的快,所以在执行的过程中我们可以简单的认为这些线程是“并发”执行的。

        上面厨师做菜的原则是:不同的切换顾客们点的菜。假设厨师做菜的原则变了,是单顾客原则:给一位顾客做完所有的菜后再给别的顾客做菜,就是说先一下子把甲点的三道菜全做出来后再去做乙点的那三道菜,这样的话如果厨师在做甲的某一道菜时发现甲点的那道菜的原料没有了,那么乙的菜就得一直等着。

         如果是在计算机中,单顾客原则执行线程的话,当一个恶性的线程运行不下去时,计算机就会出现死机的现象,这时候只能重启。

         上面介绍的厨师做菜的两种原则分别代表着计算机中线程的两种调度形式:抢占式调度和非抢占式调度。应用中我们一般用抢占式调度(即厨师的第一种做菜原则)。



堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会


切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值