volatile Synchronized <object>?obj; // volatile is sufficient for this usage public void Foo() { new Thread(() => { obj?.WithLock(o => { Console.WriteLine(o.ToString()); }); }).Start(); obj = Synchronized.Create(new object()); }
private void Dining() { for (var method = (Method)0; method < Method.Count; ++method) { for (var nt = 2; nt <= 32; ++nt) { ForceGC(); var table = new List <IBareLock>(); var lockOrders = new Dictionary <IBareLock, int>(); for (var i = 0; i < nt; ++i) { table.Add(Synchronized.Create(new object())); lockOrders[table[i]] = i; } var diners = new List <Philosopher>(); for (var i = 0; i < nt; ++i) { int j = i; int k = j < nt - 1 ? j + 1 : 0; Action <IReadOnlyList <IBareLock>, Action> lockToEat = null; switch (method) { case Method.Ordered: lockToEat = (locks, eat) => { locks = locks.OrderBy(x => lockOrders[x]).ToList(); foreach (var l in locks) { l.BarelyLock(); } eat(); foreach (var l in locks) { l.BarelyUnlock(); } }; break; case Method.SmartAndPolite: lockToEat = (locks, eat) => { using (MultiSync.All(locks)) { eat(); } }; break; } diners.Add(new Philosopher(new[] { table[j], table[k] }, lockToEat)); } var threads = new List <Thread>(); var stopwatch = new Stopwatch(); for (var i = 0; i < nt; ++i) { threads.Add(new Thread(diners[i].Dine)); } stopwatch.Start(); for (var i = 0; i < nt; ++i) { threads[i].Start(); } foreach (var t in threads) { t.Join(); } stopwatch.Stop(); Console.WriteLine($"{method},{nt},{stopwatch.Elapsed.TotalSeconds}"); } } }
private async Task TestSynchronizeMultipleAsync(int repeat, bool output) { var watch = new Stopwatch(); var x1 = new X(); var x2 = new X(); var sqrt = (int)Math.Sqrt(1); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { lock (x1) { lock (x2) { x1.Value += sqrt; x2.Value += sqrt; } } } watch.Stop(); if (output) { Console.WriteLine($"lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncMonitor1 = Synchronized.Create(x1); var syncMonitor2 = Synchronized.Create(x2); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var v1 = syncMonitor1.Lock()) using (var v2 = syncMonitor2.Lock()) { v1.Value.Value += sqrt; v2.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = MultiSync.All(new[] { syncMonitor1, syncMonitor2 })) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.All Monitor,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var syncMonitors = new[] { syncMonitor1, syncMonitor2 }; watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = MultiSync.All(syncMonitors)) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.All Monitor reusing array,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); var semaphore1 = new SemaphoreSlim(1); var semaphore2 = new SemaphoreSlim(1); for (int i = 0; i < repeat; ++i) { await semaphore1.WaitAsync().ConfigureAwait(false); await semaphore2.WaitAsync().ConfigureAwait(false); x1.Value += sqrt; x2.Value += sqrt; semaphore2.Release(); semaphore1.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.WaitAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var syncSemaphore1 = AsyncSynchronized.Create(x1); var syncSemaphore2 = AsyncSynchronized.Create(x2); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = await MultiSync.AllAsync(new[] { syncSemaphore1, syncSemaphore2 }).ConfigureAwait(false)) { guard.Value[0].Value += sqrt; guard.Value[1].Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"MultiSync.AllAsync SemaphoreSlim,{((double)watch.ElapsedTicks * 100 / repeat)}"); } }
public async Task TestSynchronizedAsync(int repeat, bool output) { var watch = new Stopwatch(); var x = new X(); var sqrt = (int)Math.Sqrt(1); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { lock (x) { x.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncMonitor = Synchronized.Create(x); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { syncMonitor.WithLock((v) => v.Value += sqrt); } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.WithLock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = syncMonitor.Lock()) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"Synchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); var semaphore = new SemaphoreSlim(1); watch.Restart(); for (int i = 0; i < repeat; ++i) { semaphore.Wait(); x.Value += sqrt; semaphore.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.Wait,{((double)watch.ElapsedTicks * 100 / repeat)}"); } var syncSemaphore = AsyncSynchronized.Create(x); ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { syncSemaphore.WithLock((v) => v.Value += sqrt); } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.WithLock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = syncSemaphore.Lock()) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.Lock,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { await semaphore.WaitAsync().ConfigureAwait(false); x.Value += sqrt; semaphore.Release(); } watch.Stop(); if (output) { Console.WriteLine($"SemaphoreSlim.WaitAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { await syncSemaphore.WithLockAsync((v) => v.Value += sqrt).ConfigureAwait(false); } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.WithLockAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } ForceGC(); watch.Restart(); for (int i = 0; i < repeat; ++i) { using (var guard = await syncSemaphore.LockAsync().ConfigureAwait(false)) { guard.Value.Value += sqrt; } } watch.Stop(); if (output) { Console.WriteLine($"AsyncSynchronized.LockAsync,{((double)watch.ElapsedTicks * 100 / repeat)}"); } }