我必须生成19位随机数。但是,存在一个约束 - 运行某些代码时,两个线程可能不会生成相同的随机数。
最简单的解决方案是锁定整个代码。但是,我想知道是否存在非锁定解决方案。我想,我可以在生成的随机数中包含ManagedThreadId,但是因特网上的ManagedThreadId文档提到它可能跨越整个Int32范围。非托管线程ID似乎限制为11位,这仍然只留下8个真正的随机位。
还有其他方法吗?以某种方式利用线程本地存储,可能是?
感谢。
修改
我想澄清一些事情。随机数可能会重复,这最终是不可避免的。我希望避免的是,如果两个线程同时输入某段代码,那么这些线程可能不会使用相同的随机数。执行代码之前或之后 - 很好,但不在代码本身内。同样,我可以使用一些锁定方案来阻止它,但我想首先检查非锁定方案。
编辑2
阅读我的问题的评论/答案我已经理解我无法避免但是要锁定特定的代码。然而,为了纯粹的学术好奇心,我仍然有兴趣知道是否有人知道我的原始问题的一个很好的解决方案 - 在多个线程中生成19位随机数,其中数字保证在线程之间是不同的,因为ManagedThreadId可能非常大,如此之大以至于只是在随机数内聚合它是不好的 - 为实际的随机位留下了空间。
答案 0 :(得分:2)
你实际上要使用多少线程?这是限制因素。如果您只需要(比方说)8个线程,那么您可能会丢失3位信息。您可以创建一个“生成器工厂”,它知道允许创建多少个生成器,并在尝试创建太多时抛出异常。
您对不同数字的要求不是很清楚 - 即使您确保一个线程永远不会创建与另一个线程创建的相同的数字,您仍然需要担心是否创建了重复的数字 on相同的线程。这对你来说是个问题吗?
答案 1 :(得分:2)
使用线程本地存储来保存对System::Random
对象的引用。给每个线程自己的RNG(你可以很容易地告诉你,如果你还没有分配一个),你可以随心所欲地从每个线程中提取值。包装代码以获取方法中特定于线程的随机数可能是一个好主意,这样您只需要一次就能完成。
[编辑:包含示例]
class example {
[ThreadStatic]
static Random threadLocalRandom;
private int GimmeARandomNumber(int upperBound) {
Random r = threadLocalRandom;
if (r == null) {
r = threadLocalRandom = new Random();
}
return r.Next(0, upperBound);
}
}
答案 2 :(得分:1)
如果你真的永远不能在线程之间或同一个线程中重复一个数字(该部分不是100%清除),那么常规随机数生成器将不适合你。创建1到N之间的数字的生成器在下次要求生成前一个数字时有1到N的机会。
如果随机数的总数有合理的上限,则将其称为N,对于特定的运行,您可以考虑创建一个从1到N的数组。顺序填充该数组的数字从1到N,然后使用shuffling algorithm对数字进行排序。如果你有M个线程,你可以对混洗数组进行分段,使第一个线程使用索引0,M,2M;第二个线程使用索引1,M + 1,2M + 1等,确保您不会访问经过混洗数组的末尾。
对于相当大的N,这是一个内存密集型解决方案,因此可能不适合您的问题。如果你被允许在给定的线程上重复相同的随机数,而不是在线程之间,Jon的解决方案更加资源友好。