using System; using System.Linq; using System.Collections.Generic; using System.Collections.Concurrent; using System.Reflection; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; var values = new ConcurrentDictionary(StringComparer.Ordinal); using var factories = new Barrier(2); int calls = 0; int[] results = new int[2]; int Factory(string key) { int candidate = Interlocked.Increment(ref calls); if (!factories.SignalAndWait(TimeSpan.FromSeconds(5))) throw new TimeoutException(); return candidate; } OwnedThreads.Run(() => results[0] = values.GetOrAdd("a", Factory), () => results[1] = values.GetOrAdd("a", Factory)); Console.WriteLine($"shared:{results[0] == results[1] && results[0] == values["a"]}"); Console.WriteLine($"entries:{values.Count}"); Console.WriteLine($"factory-calls:{calls}"); public static class OwnedThreads { public static void Run(params Action[] actions) { var errors = new ConcurrentQueue(); var threads = actions.Select(action => new Thread(() => { try { action(); } catch (Exception error) { errors.Enqueue(error); } }) { IsBackground = true }).ToArray(); foreach (var thread in threads) thread.Start(); foreach (var thread in threads) if (!thread.Join(TimeSpan.FromSeconds(8))) throw new TimeoutException("Owned worker did not finish"); if (!errors.IsEmpty) throw new AggregateException(errors); } }