public async Task TestLoadSyncAndAsync()
        {
            var l = new AsyncReaderWriterLock();
            var lockStatistics     = new LockStatistics();
            var incorrectLockCount = false;
            var tasks                   = new Task[20];
            var masterRandom            = new Random();
            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));

            for (var i = 0; i < tasks.Length; i++)
            {
                // Ensure that each random has its own unique seed
                var random = new Random(masterRandom.Next());
                tasks[i] = i % 2 == 0
                                        ? Task.Run(() => Lock(l, random, lockStatistics, CheckLockCount, CanContinue))
                                        : LockAsync(l, random, lockStatistics, CheckLockCount, CanContinue);
            }

            await Task.WhenAll(tasks);

            Assert.That(incorrectLockCount, Is.False);

            void CheckLockCount()
            {
                if (!lockStatistics.Validate())
                {
                    Volatile.Write(ref incorrectLockCount, true);
                }
            }

            bool CanContinue()
            {
                return(!cancellationTokenSource.Token.IsCancellationRequested);
            }
        }
        private static async Task LockAsync(
            AsyncReaderWriterLock readWriteLock,
            Random random,
            LockStatistics lockStatistics,
            System.Action checkLockAction,
            Func <bool> canContinue, CancellationToken cancellationToken = default(CancellationToken))
        {
            while (canContinue())
            {
                var isRead   = random.Next(100) < 80;
                var releaser = isRead ? await(readWriteLock.ReadLockAsync()) : await(readWriteLock.WriteLockAsync());
                lock (readWriteLock)
                {
                    if (isRead)
                    {
                        lockStatistics.ReadLockCount++;
                    }
                    else
                    {
                        lockStatistics.WriteLockCount++;
                    }

                    checkLockAction();
                }

                await(Task.Delay(10, cancellationToken));

                lock (readWriteLock)
                {
                    releaser.Dispose();
                    if (isRead)
                    {
                        lockStatistics.ReadLockCount--;
                    }
                    else
                    {
                        lockStatistics.WriteLockCount--;
                    }

                    checkLockAction();
                }
            }
        }
        private static void Lock(
            AsyncReaderWriterLock readWriteLock,
            Random random,
            LockStatistics lockStatistics,
            System.Action checkLockAction,
            Func <bool> canContinue)
        {
            while (canContinue())
            {
                var isRead   = random.Next(100) < 80;
                var releaser = isRead ? readWriteLock.ReadLock() : readWriteLock.WriteLock();
                lock (readWriteLock)
                {
                    if (isRead)
                    {
                        lockStatistics.ReadLockCount++;
                    }
                    else
                    {
                        lockStatistics.WriteLockCount++;
                    }

                    checkLockAction();
                }

                Thread.Sleep(10);

                lock (readWriteLock)
                {
                    releaser.Dispose();
                    if (isRead)
                    {
                        lockStatistics.ReadLockCount--;
                    }
                    else
                    {
                        lockStatistics.WriteLockCount--;
                    }

                    checkLockAction();
                }
            }
        }