아래 프로그램을 만들었으므로 ThreadLocal 필드보다는 매개 변수를 사용하는 것이 빠릅니다.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestThreadLocal
{
internal class Program
{
public class EvaluationContext
{
public int A { get; set; }
public int B { get; set; }
}
public static class FormulasRunTime
{
public static ThreadLocal<EvaluationContext> Context = new ThreadLocal<EvaluationContext>();
public static int SomeFunction()
{
EvaluationContext ctx = Context.Value;
return ctx.A + ctx.B;
}
public static int SomeFunction(EvaluationContext context)
{
return context.A + context.B;
}
}
private static void Main(string[] args)
{
Stopwatch stopwatch = Stopwatch.StartNew();
int N = 10000;
Task<int>[] tasks = new Task<int>[N];
int sum = 0;
for (int i = 0; i < N; i++)
{
int x = i;
tasks[i] = Task.Factory.StartNew(() =>
{
//Console.WriteLine("Starting {0}, thread {1}", x, Thread.CurrentThread.ManagedThreadId);
FormulasRunTime.Context.Value = new EvaluationContext {A = 0, B = x};
return FormulasRunTime.SomeFunction();
});
sum += i;
}
Task.WaitAll(tasks);
Console.WriteLine("Using ThreadLocal: It took {0} millisecs and the sum is {1}", stopwatch.ElapsedMilliseconds, tasks.Sum(t => t.Result));
Console.WriteLine(sum);
stopwatch = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
int x = i;
tasks[i] = Task.Factory.StartNew(() =>
{
return FormulasRunTime.SomeFunction(new EvaluationContext { A = 0, B = x });
});
}
Task.WaitAll(tasks);
Console.WriteLine("Using parameter: It took {0} millisecs and the sum is {1}", stopwatch.ElapsedMilliseconds, tasks.Sum(t => t.Result));
Console.ReadKey();
}
}
}
'ThreadLocal <>'에서 '유용성 패널티'에 대해 생각해 보셨습니까? 라이브러리 소비자가 멀티 스레드 된 경우 어떻게해야합니까? –
@Eugen Rieck - 단일 액터 스레드를 통해 모든 호출을 직렬화 할 수 있다고 가정하지만 런타임 자체가 이미 스레드 안전성이있을 수 있으므로 사소한 편의를 위해 상당한 오버 헤드가 추가됩니다. – ChaosPandion
@Eugen Rieck- "유용성 패널티"란 말의 의미를 이해합니다. 내 라이브러리의 소비자는 멀티 스레드이지만, 하나의 공식을 계산하기위한 요청은 하나의 문맥에서 하나의 스레드에서만 발생합니다. 하지만 다른 스레드에서 동일한 런타임 함수를 호출 할 수 있으므로 각 스레드에 대한 컨텍스트를 설정할 필요가 있습니다.런타임 함수는 매개 변수 및이 ThreadLocal 컨텍스트 멤버를 통해 필요한 모든 기능을 제공하므로 스레드로부터 안전합니다. – costa