Ber*_*ryl 8 .net c# random .net-3.5
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
new Random(Interlocked.Increment(ref seed))
);
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}
Run Code Online (Sandbox Code Playgroud)
我想在.NET 3.5项目中使用相同的概念,因此ThreadLocal不是一个选项.
如果没有ThreadLocal的帮助,你如何修改代码以拥有一个线程安全的随机提供程序?
好的,我现在和Simon的[ThreadStatic]一起去,因为我最了解它.这里有很多好的信息可以随着时间的推移进行审核和重新思考.谢谢大家!
public static class RandomProvider
{
private static int _seed = Environment.TickCount;
[ThreadStatic]
private static Random _random;
/// <summary>
/// Gets the thread safe random.
/// </summary>
/// <returns></returns>
public static Random GetThreadRandom() { return _random ?? (_random = new Random(Interlocked.Increment(ref _seed))); }
}
Run Code Online (Sandbox Code Playgroud)
如果没有ThreadLocal的帮助,你如何修改代码以拥有一个线程安全的随机提供程序?
Jon在您链接的文章中回答了您的问题:
使用一个实例,但也使用一个锁,每个调用者在使用随机数生成器时必须记住这个锁.这可以通过使用为您执行锁定的包装器来简化,但在多线程系统中,您仍然可能浪费大量时间等待锁定.
所以每次在包装器中锁定它,并在完成后解锁它.
如果它足够便宜,很好,它足够便宜.
如果这不够便宜,那么你有两个选择.首先,让它更便宜.其次,编写一个伪随机数生成器的线程安全实现,可以在不锁定的情况下使用.
有很多方法可以降低它的价格.例如,你可以换空间时间; 你可以在程序启动时生成一个十万个随机数的数组,然后编写一个无锁算法,从数组中提供先前计算的随机值.当您用完值时,在数组中生成另外十万个值,并将旧数组换成旧数组.
这有一个缺点,它的内存消耗大约是它的十万倍,并且每十万个数字突然变得非常慢,然后再次加速.如果这是不可接受的,那么提出一个可以接受的策略.你是那个知道什么是可接受的表现而不是什么的人.
或者,就像我说的那样,如果你不喜欢为你提供的那个,那就写下你自己的.使用可接受的性能编写Random的线程安全实现,并从多个线程中使用它.
我看到了Jon所说的关于锁定包装器的内容,但不确定代码的样子!
就像是:
sealed class SafeRandom
{
private Random random = new Random();
public int Next()
{
lock(random)
{
return random.Next();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,每当你打电话给Next时,你都会锁定.(总是锁定一个私有对象 ;这样你知道你的代码是锁定它的唯一代码!)如果两个线程同时调用Next,那么"loser"会阻塞,直到"winner"离开Next方法.
如果您愿意,您甚至可以将SafeRandom对象设为静态类:
static class SafeRandom
{
private static Random random = new Random();
public static int Next()
{
lock(random)
{
return random.Next();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以从任何线程调用SafeRandom.Next().
[ThreadStatic]
private static Random _random;
private static Random Random
{
get
{
int seed = Environment.TickCount;
return _random ?? (_random = new Random(Interlocked.Increment(ref seed)))
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1146 次 |
最近记录: |