【问题标题】:Unique integer multiple threads唯一整数多线程
【发布时间】:2021-11-06 08:01:50
【问题描述】:

我正在尝试生成可以从多个线程中使用的唯一 integer Id。

public partial class Form1 : Form
{
    private static int sharedInteger;
    ...

private static int ModifySharedIntegerSingleTime()
{
    int unique = Interlocked.Increment(ref sharedInteger);

    return unique;
}

SimulateBackTestRow1()
{
    while (true)
    {
        int num = ModifySharedIntegerSingleTime();
    }
}
SimulateBackTestRow2()
{
    while (true)
    {
        int num = ModifySharedIntegerSingleTime();
    }
}

Task modifyTaskOne = Task.Run(() => SimulateBackTestRow1());
Task modifyTaskTwo = Task.Run(() => SimulateBackTestRow2());

但是,当采用以前未使用过的唯一编号的代码通过ModifySharedIntegerSingleTime 获取的编号时,我会遇到与非唯一编号发生冲突。

thread-safe 方式获取唯一 int Id 的正确方法是什么?

【问题讨论】:

标签: c# multithreading task-parallel-library interlocked


【解决方案1】:

您只有 2^32 个具有整数的唯一值。由于您在循环中尽可能快地生成值,因此生成超过约 40 亿个值需要用完并开始返回您已经使用并导致冲突的值。要么您的程序中存在一些错误,导致您生成的新值比实际需要的多,要么您需要使用具有更多值的类型,例如 long 或 GUID。

【讨论】:

  • 更糟糕的是,整数大致分为正数和负数,并且算法从 0 开始,所以你实际上只有一半的数字空间才会出现......错误?发生溢出时 Interlocked.Increment 的行为是什么?
  • 哈哈!是的,我也忘记了 Sleep(1) 并不意味着一秒钟 :-)
  • @TomTom 它没有错误,它只是溢出。所以它从哪里开始并不重要(当将它严格用作标识符时),因为它在到达起始位置之前总是需要恰好 2^32 次调用。
  • @Ivan 我强烈建议永远不要将整数传递给睡眠。总是使用时间跨度,这样你就不会犯那样的错误。在您跟踪时间跨度的其他任何地方执行相同的操作,并且不要在其位置使用整数,因为单位通常不明确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 2021-10-08
  • 2021-07-22
  • 1970-01-01
相关资源
最近更新 更多