gpt4 book ai didi

c# - .Net 中 Random 的并发问题?

转载 作者:太空狗 更新时间:2023-10-29 20:45:07 24 4
gpt4 key购买 nike

我正在用 Paint.Net plugin 调试一些问题当多个线程从单个实例调用一个方法时,我偶然发现了 Random 类的一些问题。

由于某些奇怪的原因,似乎如果我不阻止并发访问,通过同步被调用的方法,我的 Random 实例开始表现...随机(但在不好的意义上)。

在下面的示例中,我创建了数百个重复调用单个 Random 对象的线程。当我运行它时,我有时(不总是,但几乎)得到明显错误的结果。如果我取消注释 Synchronized 方法注释,则问题永远不会发生。

using System;
using System.Threading;
using System.Runtime.CompilerServices;
namespace testRandom {

class RandTest {
static int NTIMES = 300;

private long ac=0;

public void run() { // ask for random number 'ntimes' and accumulate
for(int i=0;i<NTIMES;i++) {
ac+=Program.getRandInt();
System.Threading.Thread.Sleep(2);
}
}

public double getAv() {
return ac/(double)NTIMES; // average
}
}

class Program
{

static Random random = new Random();
static int MAXVAL = 256;
static int NTREADS = 200;

//[MethodImpl(MethodImplOptions.Synchronized)]
public static int getRandInt() {
return random.Next(MAXVAL+1); // returns a value between 0 and MAXVAL (inclusive)
}

public static void Main(string[] args) {
RandTest[] tests = new RandTest[NTREADS];
Thread[] threads = new Thread[NTREADS];
for(int i=0;i<NTREADS;i++) {
tests[i]= new RandTest();
threads[i] = new Thread(new ThreadStart(tests[i].run));
}
for(int i=0;i<NTREADS;i++) threads[i].Start();
threads[0].Join();
bool alive=true;
while(alive) { // make sure threads are finished
alive = false;
for(int i=0;i<NTREADS;i++) { if(threads[i].IsAlive) alive=true; }
}
double av=0;
for(int i=0;i<NTREADS;i++) av += tests[i].getAv();
av /= NTREADS;
Console.WriteLine("Average:{0, 6:f2} Expected:{1, 6:f2}",av,MAXVAL/2.0);

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}

示例输出(具有上述值):

Average: 78.98   Expected:128.00
Press any key to continue . . .

这是一些已知问题吗?在不同步的情况下从多个线程调用 Random 对象是否不正确?

更新:根据答案,文档声明随机方法不是线程安全的 - 我的错误,我应该阅读它。也许我以前读过,但并不认为它如此重要——人们可能(草率地)认为,在极少数情况下,两个线程同时进入同一个方法,最糟糕的情况是这些调用得到错误的结果——而不是如果我们不太关心随机数的质量,这是一件大事……但问题确实是灾难性的,因为对象处于不一致的状态,并且从那时起它一直返回零——如前所述here .

最佳答案

For some strange reason

这并不奇怪 - Randomdocumented不是线程安全的。

这是一种痛苦,但这就是生活。看我的article on Random了解更多信息,以及如何为每个线程创建一个实例的建议,并防止在多个线程中使用相同的种子启动。

关于c# - .Net 中 Random 的并发问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5915364/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com