私は、並列ランダムジェネレータにThreadLocalを使用しようとしています。私のテストコードは、次のようなものです:ThreadLocalを並列ループの間に置くことは良い/悪い考えですか?
class Program
{
static void Main()
{
using (MyClass myClass = new MyClass())
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("\nPass {0}: ", i + 1);
myClass.Execute();
}
Console.WriteLine("\nRandom Generators used: {0}", myClass.ListRNG.Count);
}
Console.WriteLine("\nPress any key...");
Console.ReadKey();
}
}
sealed class MyClass : IDisposable
{
ThreadLocal<RandomGenerator> threadRNG = new ThreadLocal<RandomGenerator>(() =>
new RandomGenerator(), true);
public IList<RandomGenerator> ListRNG { get { return threadRNG.Values; } }
public void Execute()
{
Action<int> action = (i) =>
{
bool repeat = threadRNG.IsValueCreated;
List<int> ints = new List<int>();
int length = threadRNG.Value.Next(10);
for (int j = 0; j < length; j++)
ints.Add(threadRNG.Value.NextInt(100));
Console.WriteLine("Action {0}. ThreadId {1}{2}. Randoms({3}): {4}",
i + 1, Thread.CurrentThread.ManagedThreadId,
repeat ? " (repeat)" : "", length, string.Join(", ", ints));
};
Parallel.For(0, 10, action);
}
public void Dispose()
{
threadRNG.Dispose();
}
}
class RandomGenerator : Random
{
public RandomGenerator() : base(Guid.NewGuid().GetHashCode())
{
}
public int NextInt(int maxValue)
{
return base.NextDouble() >= .5 ? base.Next(maxValue) : -base.Next(maxValue);
}
}
並列ループの複数の実行の間にThreadLocalを維持するのは良いことか悪いのですか?私は、RandomGeneratorの未使用のインスタンスが蓄積するかもしれないと思います。特に私は何千人もの執行をしています。
更新: 私は別のThreadLocalコンストラクタで別のバージョンのテストを試み、すべての値にアクセスできるようにしました(私は上記のコードを変更しました)。
また、myClass.Execute()を100,000回実行したところ、RandomGeneratorインスタンスが17個しか作成されていませんでした。だから、私は(私が望む)そのようなアプローチですべてがOKだと思う。
スレッドが完了すると、ThreadLocal.Dispose()を呼び出すことになっています。私はどちらも気にしないでしょう。たぶん、これは少し過剰なもので、あなたはランダムなスレッドセーフを行うことができますか?それはちょうどロックを取る。このような偽のコードでは、タイミングはそれほど良いものではありませんが、それはあまり意味がありません。 –
@HansPassant、私は[this](https://blogs.msdn.microsoft.com/pfxteam/2009/02/19/getting-random-numbers-in-a-thread-safe-way/)に私のコードを基づいています。と[this](https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness/)の記事をご覧ください。私は遺伝的アルゴリズムでそれを使用する予定なので、タイミングは重要です。この場合、ロックを使う方が良いとは思わない。 – quicktrick
さて、明らかなことをしてください。あなたの気持ちを良くするために、ThreadLocalのDispose()メソッドを呼び出します。または、あなたがそれのコストを見過ごすことはないからです。それはあなた次第です。 –