我有以下代码。 在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;
}
}
答案 0 :(得分:3)
锁定完全没必要;问题是DateTime.Now
只有大约15毫秒的粒度(取决于你的系统)。首先不要把时间当作身份证;你可以轻而易举地做这样的事情:
public static class Util
{
static long _id;
public static string GetId()
{
return Next().ToString("0000000000000000");
}
private static long Next()
{
return Interlocked.Increment(ref _id);
}
}
答案 1 :(得分:2)
虽然我建议远离这种生成密钥的方法,但是如果你受到其他条件的限制,那么你可以在不强迫等待的情况下修复代码的一种方法是保持对最后生成的id的引用,然后在生成的ID仍然匹配旧的,睡眠(10)左右。
这将保留代码的所有现有属性,我认为主要的是它将在程序的运行之间保持递增,而不是像其他示例所呈现的单个会话。
答案 2 :(得分:1)
Thread.Sleep的参数以毫秒为单位,选择一个更大的数字。或者使用Guid.NewGuid()生成一个实际上唯一的ID,而不会浪费时间。
答案 3 :(得分:1)
DateTime.Ticks
能为你效力吗?它有100纳秒的分辨率,所以听起来它可能有效。你也不必锁定任何东西,IMO。
答案 4 :(得分:0)
现在您正在锁定,尝试保存先前的值,并比较相等性。如果等于,则不要返回,而是睡眠,然后再循环尝试。
就个人而言,我认为这种做法很糟糕。使用GUID,他们是你的朋友。