我想证明一个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());

我用的是c#。


当前回答

Kai,我提供了一个程序,将做什么你想使用线程。它是根据以下条款授权的:您必须向我支付每小时每CPU内核0.0001美元的费用。费用在每个日历月的月底支付。请联系我的贝宝账户详细信息在您最早的方便。

using System;
using System.Collections.Generic;
using System.Linq;

namespace GuidCollisionDetector
{
    class Program
    {
        static void Main(string[] args)
        {
            //var reserveSomeRam = new byte[1024 * 1024 * 100];     // This indeed has no effect.

            Console.WriteLine("{0:u} - Building a bigHeapOGuids.", DateTime.Now);
            // Fill up memory with guids.
            var bigHeapOGuids = new HashSet<Guid>();
            try
            {
                do
                {
                    bigHeapOGuids.Add(Guid.NewGuid());
                } while (true);
            }
            catch (OutOfMemoryException)
            {
                // Release the ram we allocated up front.
                // Actually, these are pointless too.
                //GC.KeepAlive(reserveSomeRam);
                //GC.Collect();
            }
            Console.WriteLine("{0:u} - Built bigHeapOGuids, contains {1} of them.", DateTime.Now, bigHeapOGuids.LongCount());


            // Spool up some threads to keep checking if there's a match.
            // Keep running until the heat death of the universe.
            for (long k = 0; k < Int64.MaxValue; k++)
            {
                for (long j = 0; j < Int64.MaxValue; j++)
                {
                    Console.WriteLine("{0:u} - Looking for collisions with {1} thread(s)....", DateTime.Now, Environment.ProcessorCount);
                    System.Threading.Tasks.Parallel.For(0, Int32.MaxValue, (i) =>
                    {
                        if (bigHeapOGuids.Contains(Guid.NewGuid()))
                            throw new ApplicationException("Guids collided! Oh my gosh!");
                    }
                    );
                    Console.WriteLine("{0:u} - That was another {1} attempts without a collision.", DateTime.Now, ((long)Int32.MaxValue) * Environment.ProcessorCount);
                }
            }
            Console.WriteLine("Umm... why hasn't the universe ended yet?");
        }
    }
}

PS:我想试试并行扩展库。这很简单。

使用OutOfMemoryException作为控制流感觉是错误的。

EDIT

看来这还能吸引选票。所以我已经修复了GC.KeepAlive()问题。并将其更改为与c# 4一起运行。

澄清一下我的支持条款:支持只在2010年2月28日有效。请使用时间机器仅在当天提出支持请求。

编辑2 与往常一样,GC在管理内存方面比我做得更好;以前我自己做这件事的任何尝试都注定要失败。

其他回答

GUID理论上是非唯一的。下面是你的证明:

GUID是一个128位的数字 如果不重用旧的guid,就不能生成2^128 + 1或更多的guid

然而,如果太阳的全部能量输出都用于完成这一任务,那么它在完成之前就会变冷。

GUID可以使用许多不同的策略生成,其中一些策略采取特殊措施来确保给定的机器不会两次生成相同的GUID。在特定算法中发现冲突将表明生成guid的特定方法不好,但不能证明关于guid的任何一般情况。

数到2^128,雄心勃勃。

让我们想象一下,每台机器每秒可以计算2^32个id——不是那么雄心勃勃,因为它甚至不到每秒43亿个。让我们用2^32台机器来完成这个任务。此外,让2^32个文明各自投入相同的资源来完成任务。

到目前为止,我们每秒可以计数2^96个id,这意味着我们将计数2^32秒(136年多一点)。

现在,我们所需要的是获得4294967296个文明,每个文明都有4294967296台机器,每台机器每秒能计算4294967296个id,在未来136年左右的时间里,纯粹是为了这项任务——我建议我们现在就开始这项基本任务;-)

如果GUID冲突是一个问题,我建议使用ScottGuID代替。

这将持续不止几个小时。假设它以1 GHz的频率循环(实际上它不会—它会比1 GHz慢得多),它将运行10790283070806014188970年。大约是宇宙年龄的830亿倍。

假设摩尔定律成立,不运行这个程序,等几百年,在一台速度快数十亿倍的计算机上运行,会快得多。事实上,任何运行时间比CPU速度翻倍(大约18个月)要长的程序,如果您等待CPU速度提高并在运行之前购买一个新的CPU(除非您编写它是为了让它可以在新的硬件上挂起和恢复),那么它将更快地完成。

如果你想在代码的许多地方检查guid的唯一性,你可以使用一个漂亮的小扩展方法。

internal static class GuidExt
{
    public static bool IsUnique(this Guid guid)
    {
        while (guid != Guid.NewGuid())
        { }
        return false;
    }
}

要调用它,只需调用Guid。每当你生成一个新的guid…

Guid g = Guid.NewGuid();
if (!g.IsUnique())
{
    throw new GuidIsNotUniqueException();
}

...见鬼,我甚至建议打电话两次,以确保它在第一轮就得到了正确的答案。