1

我有以下代码。在 windows server 2008 中,该程序是正确的并且可以按预期运行。它输出 10 个不同的 id。

但是,当我在 windows server 2003 中运行它时,程序不正确。它输出 10 个 id,但其中一些 id 是重复的。看来锁不工作了。

如果我设置Thread.Sleep(500),它可以在 windows server 2003 上正常工作。

class Test
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine(Util.GetId());
        }
        Console.ReadLine();
    }
}

public class Util
{
    private static object idlock = new object();

    public static string GetId()
    {
        string id = "";
        lock (idlock)
        {
            Thread.Sleep(1);
            id = System.DateTime.Now.ToString("yyMMddHHmmssffff");
        }
        return id;
    }
}
4

5 回答 5

3

锁定是完全没有必要的;问题是DateTime.Now只有大约 15 毫秒左右的粒度(取决于您的系统)。一开始就不要用时间作为id;您可以轻松地做这样的事情:

public static class Util
{
    static long _id;
    public static string GetId()
    {
        return Next().ToString("0000000000000000");
    }

    private static long Next()
    {
        return Interlocked.Increment(ref _id);
    }
}
于 2011-04-22T03:43:37.573 回答
2

虽然我建议不要使用这种生成密钥的方法,但如果您受到其他条件的限制,那么您可以在不强制等待的情况下修复代码的一种方法是保留对最后生成的 id 的引用,然后在刚刚生成的 id 仍然匹配旧的, sleep(10) 左右。

这将保留代码的所有现有属性,我认为主要是它将在程序的运行之间不断增加,而不是像其他示例那样的单个会话。

于 2011-04-22T04:09:55.503 回答
1

Thread.Sleep 的参数以毫秒为单位,选择一个更大的数字。或者使用 Guid.NewGuid() 生成一个真正唯一的 ID 而不会浪费时间。

于 2011-04-22T03:16:10.927 回答
1

DateTime.Ticks为你工作吗?它有 100 纳秒的分辨率,所以听起来它可以工作。IMO,您也不必锁定任何东西。

于 2011-04-22T03:35:45.923 回答
0

现在您正在锁定,尝试保存先前的值,并比较是否相等。如果等于,则不返回,而是在循环中休眠并重试。

就个人而言,我认为这种方法很糟糕。使用 GUID,它们是您的朋友。

于 2011-04-22T04:19:30.693 回答