上周末,终于在各种剧透和解构的隆隆声中看完了期待已久的《Inception》,不得不说,不白花这些钱。
之前在豆瓣上看到一篇讲Inception里面的数学原理的帖子,其实哪有那么深奥。
依我看,Christopher Nolan简直就是个程序员的脑子,还到不了理论数学家的高度。为什么说是程序员呢,让我把《Inception》用程序员的语言由浅入深地解释一下。
本片最主要的设定是什么呢?梦中梦对不对?这在程序的角度来说再直观不过了,那就是——递归,如果做梦是一个函数Dream,那么梦中梦就是该函数的递归调用。
比起一般的递归调用来,该程序的特殊之处是,它是一个多线程的递归调用,也即是说每一次递归都会新建一个线程来执行函数体。因此该递归函数有两种结束机制,一种是wait超时(药物失效),另一种是由其调用函数来结束(kick)。
而由于硬件平台所限,该递归只能进行四层,因为每次递归都需要消耗系统资源,所以递归深一层,系统运行就越慢(梦境每深一层,时间就变慢20倍)。一旦在第四层的时候资源耗尽(做梦者生命耗尽),就会产生栈溢出,因此线程就会进入僵死状态(limbo状态)。
而一旦将运行超时时间设置得过长(强力镇静药物),则会导致子线程运行过长从而耗尽资源。此时如果子线程还没有被上层调用函数强制结束(撞击),则会被detach(在梦中死去),因此进入僵死状态(进入limbo状态)。
而为什么多层次的梦唤醒需要同步撞击呢,这就跟我们析构一个含有指针的STL容器一样,如果不遵守顺序,那么就会出现容器被析构而指针内容还在从而发生内存泄露的问题。
再来解释一下,为什么Cobb在limbo状态能找到所有死去的同伴,同时通过直接自杀直接返回,这里面有两个非常重要的概念,那就是GC和线程池!因为所有的僵死状态的线程都不能被其调用函数结束(kick不到了),因此只能通过垃圾回收机制也就是GC来进行回收,因为在僵死状态下,现场已经没有作用,也无法找到其调用者(在limbo状态下失忆),因此回收的机制就是将该线程杀死,并重新创建以保证线程池中的线程数稳定(这就是为啥在limbo状态下自杀可以在现实中满血复活),而因为线程池是一个全局的结构,当然是可以找到所有的limbo状态的人啦。当然,如果GC算法不够好,无法识别出僵死线程(齐藤失忆),那就发生了资源的泄露(既回不去,也死不了)。
大体设定就这些,然后看看剧情,也就是我们的线程体要怎么写,作为一个盗梦团队,Inception的目的其实跟计算机安全中的缓冲区溢出攻击是同理的,那就是利用程序漏洞(人的性格弱点),向其地址空间(头脑)植入可执行代码(想法),从而可以在对手的系统(大脑)中执行自己的特权指令(解散Fisher的公司)。
而按照剧情中,深层次的意识在浅层次的梦境中将被放大的设定,我们可以将该线程函数体写成如下:
01dream(timer)
02{
03 thought = 0;
04 if(buffer_overflowed)
05 {
06 thought = new Thought(I_Want_My_Own_Life);
07 }
08 if(thought == 0 )
09 {
10 p = new_thread(dream());
11 wait_for_timer_then_kick(timer * 20, p);
12 }
13 else return thought * magnifier;
14}
到此,影片的大纲已经基本成型,其实还有很多细节都是符合计算机程序设计思维的,只是作为程序员,没有闲再继续扯下去了……