当你看到窗口的标题栏上出现了 “没有响应” (No Responding) 四个字,电脑陷入了莫名的卡顿的时候,你一拍脑袋,大喝一声 “又死机了!” ,点下结束进程的你是否想过,这玩意,真的死机了吗?有时莫名卡顿了几分钟后,程序又莫名其妙恢复正常了。这又是什么情况呢?
首先,我们先来理解一下,什么是 “没有响应”,微软的官方帮助告诉我们:表示该程序与 Windows 的连接速度比平常慢,一般原因是程序中出现问题。如果我们深入理解一下的话,我们可以先考虑一下带窗口界面的程序通常的运行形式。
一个程序通常可以拥有很多线程,意味着它可以同时干很多事。然而通常只有主线程是可以用来更新窗口上显示的内容的,别的线程只能在背后默默进行计算、网络通讯等其它工作。对于同一个线程,一次只能干一件事。主线程虽然更新界面,但大多数情况下,它也会进行一些运算。但如果这个线程长达数秒都迟迟无法更新界面,也就是说这个线程在运行某些内容时阻塞了,系统就会认为这是程序 “没有响应” 了。没有响应通常有两种可能性,第一种是程序运行出现了死循环,怎么也跑不出来了,这就是我们常说的死机。为了帮助大家理解这种 “死循环”,大家可以思考一下下面这个程序:
第一步:运行 1+x
第二步:如果上一步运行结果是2,那么重新运行第一步
第三步:显示结果
非常显然,当 x=1 时,这个程序将无限在一二步中循环,这就是传说中的死循环。死循环会导致主线程阻塞(如果这个运算在主线程执行的话)。这就会出现 “没有响应” 的情况。
当然造成 “没有响应” 并不止这一种可能,另一种可能那就是主线程真的在执行某个计算很费时的运算。比如运算小于10000000000000的所有素数,这由于算的时间太长也会阻塞主线程,导致 “没有响应”。不过这种阻塞是暂时的,并不是真正的死循环,稍等片刻也是可以解出来的。
然而,为什么系统不能区分出这两种阻塞哪一种是真正的死循环而哪一种只是运算太慢了呢?因为。。。真的不能。。。区分。。。
这种 “不能”,是数学意义上证明的,它就是不能。
给出这个证明的是年仅24岁的计算机科学之父——艾伦·图灵,证明这个问题,这篇论文有近40页(原文),不过实际上的证明过程,只需要一张纸就能说明了。
还是以刚刚演示的会死循环的程序为例,显然这个程序在 x=1 时发生死循环,我们记这个程序为 F(x),当 x=1 时死循环。我们假设存在一个程序能判定程序是不是会死循环,我发这个程序叫 G(f,x),指该程序可以判定程序f是否在输入x时会死循环。如果判定为死循环就返回1,正常运行就返回0。所以显然 G(F,1) = 1,G(F,2)=0。
我们现在再构造一个更恶心的函数,它叫T(f,x),它内部会先运行G(f,x),如果发现G(f,x) = 1就正常退出,而如果 G(f,x)=0 时就让自己死循环。
那么问题来了,T(T,x)会不会死机呢?
我们可以假设T(T,x)是不死机的,那么意味着G(T,x)返回的是1,而G(T,x)返回1的前提是T(T,x)是死机的,相矛盾,反之同样矛盾。由此证明,一个判断程序是否可能死机的函数 G(f,x) 不存在。
这就是著名的图灵停机问题,在80年前还没有计算机的时候,图灵就证明了这个问题。
不过图灵的这个证明恰好证明了另一个问题,那就是希尔伯特的23个问题。这是德国数学家大卫·希尔伯特(David Hilbert)于1900年在巴黎举行的第二届国际数学家大会上所提出23道最重要的数学问题中的第2个问题 —— 算术公理之相容性。这个问题其本质是希望找到一个方法证明任意公理系统的内部是不矛盾的。
但实际上是事与愿违的,许多公理系统都是自相矛盾的。图灵的停机问题就是这样一种自相矛盾的一个证明。当然,一些更熟悉更易理解的问题其实也可以证明这样的问题。
比如最常见的是 罗素悖论 的一个通俗描述,那就是 理发师悖论。一个理发师给所有不给自己理发的人理发,那么他给不给自己理发?这时候无论理还是不理,都是相矛盾的。
罗素悖论的相对深入的通俗描述可以这么理解:比如一个集合:世界上所有描述它字数少于100字的集合都是这个集合的子集。这个描述本身是完备的,但显然这个集合本身也是自己的子集,并且这个集合包含的还不止有自己集合本身,意味着这个集合本身是自己的真子集,这就是非常荒谬而矛盾的了。
无论图灵还是罗素提出的悖论都证明了我们的计算系统存在不完备的漏洞,然而 1931 年数学家库尔特·哥德尔给出了更为完整的证明,这个证明直接把这种不完备提升到了一个巨大的前提下:任何相容的形式系统,只要蕴涵皮亚诺算术公理,就可以在其中构造在体系中不能被证明的真命题,因此通过推演不能得到所有真命题(即体系是不完备的)。
也就是说,任何形式的数学系统,只要包含关于自然数最最基础的公理:皮亚诺公理,那么它就是不完备的,如此残念。
我看到了它,却不敢相信它。
——康托尔
当然,我从来不是一个喜欢如此无聊地聊数学的人,今天不由来说说这个坑爹的定理的原因其实非常简单,因为开源哥发了这么一张图: