一个线程的自传:出生、死亡和重生。
图片来源 Justin Lim于 Unsplash
1. 一个新手
我是一个线程。我出生时的号码是0x3704,然后被带到一个黑暗的房间,在那里我找到了很多和我一样的朋友。
我的同伴0x6900在这里呆了相当长的时间。他用一种老练的语气对我说。"我们这些人的命运就是处理包裹。你必须在处理完包裹后立即回到这里,否则你可能永远不会回来。"
我天真地问道。"包裹?什么包?"
"别担心,你很快就会发现的。我们这里不养闲人。"
没过多久,门就开了。一个凶神恶煞的家伙大喊:"0x3704,出来!"
一个沉重的包裹压在我身上。还有一份列出操作步骤的文件。
"走,出去处理这个包裹。"
"但去哪里呢?"
"遵循指示。首先到 "可运行车间"。"
我在地上发现了一个箭头。它把我引向一间明亮的房子,里面已经容纳了一些线人。每个人似乎都很紧张,随时准备冲上前去。
我一进来就听到无线电说:"0x3704,进入运行车间。"
我走得更快了。有人在我身后说话。
"这样一只幸运的狗!他能在可跑之后马上跑起来!"
"也许他认识某个人。"
"不,他有更高的优先权。唉!"。"
运行车间就在我面前。它是如此美丽。难怪老线程一直唠叨说他想永远留在这里。
房间更大,视野更好。空气清新而芬芳。有许多工人等着为我服务。
它们都有数字。更重要的是,它们有 "硬盘"、"数据库"、"内存"、"网卡 "等标签。
只是当时我不知道他们的工作。让我们检查一下操作步骤。
第一步 解开参数的包装
里面有一个HttpRequest对象,包括两个参数:userName和password。
第二步 进行登录操作
嗯,有人试图登录。我把用户名和密码交给了数据库服务员。他慢慢地离开了。
但他为什么这么慢呢?总之,我可以在这里多待一会儿,因为第三步是不能操作的。
就在这时,广播说:"0x3704,我是CPU。记住你要走的步骤,然后马上带着包裹离开!"。"
我慢慢地开始收拾我的东西。
"快点,另一条线即将进入。"
我离开这个车间,进入另一个大房间,里面有很多线程在喝茶,懒洋洋地打牌。
"老兄,你现在无事可做?"
"你一定是新来的。我正在等待数据库服务员给我的数据。据说他们的速度比我们慢几十万倍。让我们在这里好好休息一下吧。"
"他们多慢啊!我这里有人在等着登录,他们能等那么久吗?"
"放松,难道你不知道现实中的一天等于CPU的一年吗?我们的时间是以纳秒和毫秒计算的。因此,现实中的一秒钟相当于我们世界中的几天。我们肯定能做到这一点。"
也许我可以睡一会儿了。一段时间后,扩音器又开始工作了。"0x3704,你的数据来了,去执行吧!"
我转身跑向CPU车间,才发现这是一扇单向的门。我无法通过这扇门进入车间。
后面传来一阵轰然大笑。"他肯定是个新手。他甚至不知道我们需要在 "可运行车间 "等待!"
我匆匆赶到可运行车间。这次很不走运,我等了很久才进入CPU车间。
当我在等待时,我听到人们在窃窃私语。
"你知道吗,最近有一个线程被杀了。"
"但为什么?"
"那个人拒绝离开CPU车间,导致CPU利用率保持100%。所以他被杀了。"
"当时他在哪里?"
"也许他是作为一个垃圾被收集起来的。"
我偷偷地打了个寒颤,加快了工作速度。第二步已经完成。
第三步 成功登录后建立主页
这一步有点耗费时间,因为有很多HTML需要处理。不管是谁写的代码,对我来说都是一个恼人的工作。
当我忙着操作HTML时,CPU又开始大叫。
"0x3704,这里是CPU。记住你所运行的步骤,然后马上带着包裹离开!"。"
"我为什么要这样做?"
"每个线程只能在CPU上运行一段时间,然后就会轮到其他人。因此,请到可运行车间等待轮到你。"
然后我在 "可运行"、"等待 "和 "运行 "之间多次切换,最后按照步骤表完成了工作。
最后,包含HTML的包被成功送回。至于登录后的情况,我并不关心。马上就要回到我的小黑屋了。我觉得有点不甘心。
但与其他一些螺纹相比,我已经很幸运了。它们在手术后被完全摧毁,而我还活着!"。
回到小黑屋,我被老线程0x6900问住了。
"你的第一天怎么样了?"
"我们这个世界的规则很复杂。首先,你不知道什么时候轮到你;其次,在执行过程中,你可能随时被打断,被要求离开CPU车间;第三,一旦有涉及硬盘或数据库的耗时操作,你需要离开CPU等待;第四,即使你有数据,也有可能不能马上开始工作。你得等着CPU来调度。"
"够了,伙计。"
"我只是不明白为什么有些线程在完成工作后就死了,而我们还活着。"
"你知道吗,永恒是我们的特权。我们的地方有一个正式的名字:线程池。"
2. 取得进展
作为一个线程,我的日常生活是由捡拾包裹、处理包裹和回到线池,我的黑暗家园组成的。
有一天,当我回来的时候,我听到一位弟兄说:"今天好好休息吧。明天将是一个疯狂的日子。"我看了看日历,明天是11月的第四个星期五。
果然,当午夜的钟声响起时,那些人类开始疯狂地递送包裹。为了应对大量涌入的包裹,线程库中没有人能够闲下来。我们所有人都出去处理包裹了。CPU车间的利用率超级高。硬盘在嗡嗡作响,网卡的灯在疯狂闪烁。虽然我们非常努力地工作,但包裹还是迅速堆积起来。
我们也无能为力。有太多的包裹,主要是浏览网页、下订单、购买、购买和购买。
包裹堆逐渐消失了。我终于可以喘口气了。我想我永远不会忘记今天。
通过这些,我意识到我生活的世界是一个电子商业网络。
我每天做的工作是处理登录、浏览、购物车、订单和付款。
我问老工人0x6900:"我们应该工作多长时间?"
"直到系统重新启动。"0x6900说。
"你曾经经历过系统重启吗?"
"不,系统重新启动将是我们的葬礼挽歌。它是启示录。一旦系统重启,整个线程库将被摧毁。时间和空间都将消逝。一切都会重新开始。"
"那么是什么时候呢?"
"我不能说。只是享受你的日子。"
生活其实是很丰富多彩的。我最喜欢的套餐是上传图片。由于网络很慢,我可以在CPU车间呆很长时间,遇到很多有趣的线程。
例如,我遇到了线程Memcached。他告诉我,在他的帮助下,电子商业网络保存了许多用户数据,而且它们分布在许多机器上。
我问他:"难怪登录操作变得更快。将没有必要从数据库中提取数据,因为你已经有了这些数据。哦,对了,既然你是分布式的,你有没有去过其他机器?"
"不,我只能通过网络向那台机器发送GET和PUT命令来访问数据。我不知道别的。"
上一次,当我在等待时,我遇到了一个为数据库连接工作的线程。直到那时我才意识到,还有一个连接池,几乎和我们的线程池一模一样。
"有些包裹实在是太变态了。他们要求看一整年的订单数据,这让我很难受,"他告诉我。
我说。"来吧,这对你来说是纯粹的数据。在你发送这些数据后,我必须将其构建为HTML,这比你的工作要变态得多!"。"
然后他给了我一个建议。"你必须与Memcached保持良好的关系,这样我们才能直接从他那里获取数据。让我们尽量不要频繁地调用数据库。这样,我们JDBC连接的生活就会轻松很多。"
"当然可以。关键是你需要提前将数据保存在缓存中,否则我必须询问缓存,发现没有数据,然后再求助于你。"
这就是生活。如果你不去找点乐子,你的生活怎么可能变得有意义?
3. 狭隘的逃亡
几天前,我经历了一件可怕的事情。我差点死在线程池外。事实上,我应该能预见到这一点。我当时非常不小心。
那天我处理了一些来自HTTP的存款和提款,老线0x6900特别告诉我。"在处理这些包时,你需要非常小心。你必须先获得一个锁。当你从账户中存款或取款时,记得要锁定账户。否则,其他线程会闯入并造成一些损失。在我年轻的时候,我的粗心造成了很大的麻烦。
为了 "恐吓",好心的0x6900给了我两张表,内容如下。
银行账户。账户A,余额为1000美元
- 线程1:存款
- 线程2:提款
表1-1 已解锁的多线程
表1-2 锁定的多线程
我很震惊:忘记锁定账户会造成如此严重的事故。从此以后,每当我看到存取时,我都会极其小心地处理它。幸运的是,没有发生意外。
今天,我收到一个包裹,内容是将钱从一个著名演员的账户转到一个著名导演的账户。我不会透露名字,但我可以告诉你,钱的数额真的很大。
按照旧线程的命令,我锁定了演员的账户,然后是导演的账户。
但令我惊讶的是,还有另一条线程,是的,0x7954,同时从导演的账户转钱到演员的账户。
目前的情况是这样的。
起初我不知道发生了什么事。我等了又等。几十秒过去了,什么也没发生。我以前从未经历过这样的事件。
这时我看到了0x7954号线程。他坐在那里悠闲地喝咖啡。我问他。
"伙计,我看到你在喝第八杯咖啡,你为什么不去完成你的工作?"
"好吧,你正在喝你的第九杯茶。你为什么不工作?"
"我在等待一把锁。一些混蛋就是不放。"
"我也在等待一把锁。如果我知道谁在保管它,我会把他打死。"0x7954凶狠地回答。
我偷看了他一眼,才发现他正拿着导演的锁。这正是我一直在等待的!
很明显,0x7954也发现我持有的是他一直在等待的锁。
很快,我们两个人就打了起来。
"把你的锁给我,让我先完成!"。"
"不可能。在我完成我的工作之前,我不会释放这个锁。你现在不能拥有它!"。"
争吵变成真正的战斗只需要几毫秒的时间。
更重要的是,我们两个人不仅持有这位著名导演和演员的锁,还持有许多其他的锁。越来越多的人加入了等待的队伍,围观的人挤满了整个屋子。最后,这真的成了一件大事。我们的大老板 "操作系统",我以前从来没有见过,他在这里。毕竟,大老板知道的更多。他看着我们,哼了一声,不屑地说道。
"又是死锁。"
"你们中的一个将被杀死。你们两个到这里来,抽签决定。"
它只是把我吓坏了。我战战兢兢地抽了签。幸运的是,我活下来了。
在被迫交出所有资源后,可怜的0x7954不幸被杀,消失了。我得到了导演的锁,现在可以开始工作了。大老板的 "操作系统 "像一阵风一样消失了,只有他的声音跟着消失了。
"记住,在我们这里,导演>演员,这意味着你需要在第一时间得到导演的锁定。"
因为这里不仅有导演和演员,还有很多人,大老板留下了一张表格,上面有计算资源大小的算法。计算之后,我们需要把锁从大到小。
(p.s.资源 "大小 "的计算是指通过把资源变成数字来进行比较。例如,我们可以通过字符串的hascode进行比较。)
我又回到了线程池中。每个人都听说了我的冒险,并不断向我询问细节。
面目邪恶的线程调度员把大老板的算法放在墙上。
每天早上,我们必须站在门前,以搞笑的方式大声背诵。
"记住资源锁定的顺序。记住要根据Boss的算法进行比较。记住从大到小的锁定。"
4. 再见
许多天后,我和其他线程发现了一件奇怪的事情:包裹的处理越来越容易了。不管是登录、浏览还是存钱,步骤都是一样的。一切都会回到一个固定的HTML页面。
有一次我偷偷地瞥了一眼,看到上面写着。" 系统将于今晚00:00至4:00进行维护和升级。给您带来的不便,我们深感抱歉。"
我把这件事告诉了0x6900。他叹了口气。
"唉,我们的生命已经走到了尽头。系统很快就会重新启动,我们会消失。再见,我的兄弟。"
然后这一刻终于来了。我看到房间里的东西一个接一个地消失了:等待车间、Runnable车间,甚至CPU车间。我身边的线人兄弟越来越少了。最后,只剩下我一个人了。
我在空旷的地面上大喊。"还有人吗?"
没有答复。
这一代的线程池已经完成了它的使命。
然而,下一代人即将重生。