随机数在不同进程中与相同的.Net代码冲突

Dam*_*isa 2 .net c# random multithreading multicore

在开始之前,我想指出我很确定这实际发生了.我的所有日​​志都表明它确实如此.

我想知道我是否错了,这是不可能的,是否只是非常不可能(我怀疑),或者它不是那么不可能,而且我做了一些根本错误的事情.

我在同一台服务器上运行了与Windows服务相同的4个相同代码实例.该服务器具有多核(4)处理器.

以下是代码摘要:

public class MyProcess
{
    private System.Timers.Timer timer;

    // execution starts here
    public void EntryPoint()
    {
        timer = new System.Timers.Timer(15000);  // 15 seconds
        timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
        timer.AutoReset = false;

        Timer_Elapsed(this, null);
    }

    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        string uid = GetUID();

        // this bit of code sends a message to an external process.
        //  It uses the uid as an identifier - these shouldn't clash!
        CommunicationClass.SendMessage(uid);

        timer.Start();
    }

    // returns an 18 digit number as a string
    private string GetUID()
    {
        string rndString = "";
        Random rnd = new Random((int)DateTime.Now.Ticks);
        for (int i = 0; i < 18; i++)
        {
            rndString += rnd.Next(0, 10);
        }
        return rndString;
    }
Run Code Online (Sandbox Code Playgroud)

接收这些消息的外部进程感到困惑 - 我认为因为同一个uid来自两个独立的进程.基于此,似乎该GetUID()方法为两个单独的进程返回相同的"随机"18位数字符串.

我已经使用DateTime.Now.Ticks播种了Random类,我认为它可以在线程之间提供保护 - 一个tick是100纳秒,当然两个线程无法获得相同的种子值.

我没有考虑的显然是我们不是在讨论线程,我们在讨论多核处理器上的进程.这意味着,这个代码可以从字面上在同一时间运行两次.我认为这是造成冲突的原因.

以大约15秒的间隔运行相同代码的两个进程设法在100纳秒内达到相同的代码.这可能吗?我在这里走在正确的轨道上吗?

我很感激你的想法或建议.


为了澄清,我不能真正使用GUID - 我正在与之通信的外部进程需要一个18位数字.它已经老了,不幸的是我无法改变它.

JP *_*oto 7

除非有某种原因你不能,否则你应该考虑使用GUID来达到这个目的.你将以这种方式消除碰撞.

每条评论:您可以使用GUID和64位FNV哈希并使用XOR折叠将结果置于您拥有的59位内.不像GUID那样具有防撞功能,但比你拥有的要好.


tva*_*son 5

您不希望为此目的使用随机数,您需要唯一的数字.我和@JP在一起.我认为你应该考虑使用GUID作为你的消息ID.

编辑:如果你不能使用GUID,那么想办法得到一个唯一的64位数字,并使用它的连续3位块作为8字符字母表的索引(扔掉未使用的高位).一种方法是使用一个数据库,在其中为每个新消息创建一个条目,并使用自动递增的64位整数作为键.使用密钥并将其转换为18个字符的消息ID.

如果您不想依赖数据库,您可以获得在某些条件下有效的东西.例如,如果消息在进程的生命周期中只需要是唯一的,那么您可以将进程ID用作值的32位,并从随机数生成器获取剩余的22个必需位.由于没有两个进程同时运行可以具有相同的id,因此应保证它们具有唯一的消息ID.

毫无疑问,如果您的情况不符合上述情况之一,您可以采取其他许多方法.