“简单证明GUID(全局唯一标识符)并不唯一”
GUID是什么,大家理所当然地应该都知道(百度百科介绍的GUID)。在.net framework中,微软为开发者提供了一个GUID结构,这个结构想必很多人在开发中应该已经用过,下面我们再来看一下它的备注说明:
“GUID 是一个 128 位整数(16 字节),可用于所有需要唯一标识符的计算机和网络。此标识符重复的可能性非常小。”
注意红色的标注,标识符是有重复的可能的,只不过重复的概率小之又小。到这里你我可能都会产生疑问,重复的可能性到底有多小呢?如何证明有重复呢?在stackoverflow上,一个善于思考勇于发现并提出问题挑战权威的C#开发先驱抛出了一个有趣的问答题:“Simple proof that GUID is not unique”(本文的标题就是按照英文原文标题直译过来的)。
在英文原文中,提问者说他想在一个测试程序中简单证明一下GUID并不唯一,然后给出了如下代码实现:
BigInteger begin = new BigInteger((long)0); BigInteger end = new BigInteger("340282366920938463463374607431768211456",10); //2^128 for(begin; begin<end; begin++) Console.WriteLine(System.Guid.NewGuid().ToString());
令人感到遗憾的是,“it's not working”(实际上,拷贝这份代码到VS中,编译无法通过,BigInteger的构造函数根本不存在,for循环的地方写得也不对,估计是伪代码)。
接着,我们看到了投票次数最多的正确答案:
GuidCollisionDetector
楼猪第一次看到代码的时候,精神抖擞热情洋溢地分析如下:
1、定义一个字节数组reserveSomeRam,分配一块内存空间;
2、通过HashSet对象填充GUID,直至内存不足,通过GC的KeepAlive和Collect方法,释放出预留给reserveSomeRam的内存空间,保证程序有继续运行的微小内存空间(此时,楼猪惊呼,好一段惊世骇俗奇技淫巧的NB代码啊);
3、通过两个for循环,配合并行库,通过HashSet的Contains函数证明新产生的GUID有可能产生重复(这里主要就是CPU运算的事情了,完全用不到reserveSomeRam那一块的内存,充分地利用了CPU和内存,这种思想这种境界真是令人感到匪夷所思望尘莫及,牛)。
但是看到代码中的“throw new ApplicationException("Guids collided! Oh my gosh!");”和Console.WriteLine("Umm... why hasn't the universe ended yet?");,楼猪有一种穿越的感觉。
接着楼猪仔细看了一下这个正确答案的正文回答的细节,发现这家伙从头到尾都是一种煞有介事一本正经的口气,又是版权,又是要钱,又是坐着时光机回到2010年2月28号获得技术支持的…恍然大悟,kao,真是TM的太好玩太会扯淡了。
忍耐不住好奇,怀着强烈的求知欲望,楼猪看完了所有回答,有人用数学方法证明…祝你好运;有人寄希望于未来的量子计算机显灵;有人提议组织志愿者现在就开始他们伟大的136年证明之旅;有人提议升级显卡,NVIDIA 可能会贷款赞助这个历史性的计算;有人说他可以帮忙,已经被证明了,他曾经获得过某一个GUID数字……楼猪久违地又蛋疼了。
比较起来,个人感觉还是这个回答比较靠谱:
Well if the running time of 83 billion years does not scare you, think that you will also need to store the generated GUIDs somewhere to check if you have a duplicate; storing 2^128 16-byte numbers would only require you to allocate 4951760157141521099596496896 terabytes of RAM upfront, so imagining you have a computer which could fit all that and that you somehow find a place to buy terabyte DIMMs at 10 grams each, combined they will weigh more than 8 Earth masses, so you can seriously shift it off the current orbit, before you even press "Run". Think twice!
大致意思就是说,跑完证明程序,需要大概830亿年时间和4951760157141521099596496896 TB(1TB=1024GB)的内存空间(假设每个DIMM内存有10克重,所有的内存换算成重量,大概是8个地球的重量之和)。从看似有限而又无限的时间和空间上证明,GUID重复这种概率发生的可能性实在是太太太小了,可以认为基本不可能。有一个回复说,“Personally, I think the "Big Bang" was caused when two GUIDs collided.”,即:两个GUID重复之日,宇宙大爆炸之时。
实际上,楼猪现在也是这么认为的。
您有好的方法证明GUID会重复吗?
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。