Многопоточный геттер System.IndexOutOfRangeException - C#
Формулировка задачи:
Есть такой код, так вот не могу понять почему в переменную next, которая используется как счетчик проскакивает число больше массива байтов, когда по идее запрос значения next должен пройти через геттер функцию и там в данном случае попасть в цикл, пока значение next не станет меньше размера массива байтов, но периодически 2 - 3 параллельно работающих потока с первым потоком (поток, который запускает поток Seed(0) и переходит в ожидание завершения запущенного потока) не останавливаясь в геттере забирают значение переменной next больше размера массива.
public static class Random
{
// 4 Mb Random bytes buffer
private static byte[] seedArr = new byte[4194304];
private static Thread waiter;
private static long _next;
private static long next
{
get
{
if (_next >= seedArr.LongLength && waiter == null)
{
waiter = new Thread(() => Seed(0));
waiter.Start();
waiter.Join();
waiter = null;
_next = 0;
}
while (_next >= seedArr.LongLength)
{
if (waiter != null && waiter.ThreadState == ThreadState.Running)
{
waiter.Join();
}
Thread.SpinWait(1);
}
return _next;
}
set
{
_next = value;
}
}
public static void Seed(ulong Seed)
{
if (Seed.GetType() != typeof(ulong) || Seed <= 0)
{
RNGCryptoServiceProvider CSP = new RNGCryptoServiceProvider();
byte[] bytes = new byte[8];
CSP.GetNonZeroBytes(bytes);
CSP.Dispose();
Seed = BitConverter.ToUInt64(bytes, 0);
}
{
ulong[] ticks = new ulong[4] {
ulong.MaxValue,
Convert.ToUInt64(DateTime.UtcNow.Ticks),
Convert.ToUInt64(Environment.TickCount),
Convert.ToUInt64(Thread.CurrentThread.ManagedThreadId)
};
ulong[] modules_a = new ulong[4] {
ticks[0] / ticks[1],
ticks[0] % ticks[1],
ticks[0] / ticks[2],
ticks[0] % ticks[2]
};
byte[] bytes = new byte[8];
{
byte[] bytes_t = new byte[524288];
{
byte[] sbytes = BitConverter.GetBytes(Seed);
MemoryStream bytebuff = new MemoryStream();
bytebuff.Write(sbytes, 0, sbytes.Length);
Extensions.ParallelFor(1, 4, i =>
{
byte[] tbytes = BitConverter.GetBytes(ticks[i]);
lock (bytebuff)
{
bytebuff.Write(tbytes, 0, tbytes.Length);
}
});
Extensions.ParallelFor(0, 4, i =>
{
byte[] mbytes = BitConverter.GetBytes(modules_a[i]);
lock (bytebuff)
{
bytebuff.Write(mbytes, 0 , mbytes.Length);
}
});
byte[] seedb = bytebuff.ToArray();
bytebuff.Dispose();
{
byte[] rseedb = seedb;
rseedb.Reverse();
int sl = seedb.Length, rsl = rseedb.Length;
MemoryStream buff = new MemoryStream();
buff.Write(seedb, 0, sl);
buff.Write(rseedb, 0, rsl);
for (int i = 0; i < 2; i++)
{
rseedb = buff.ToArray();
buff.Write(rseedb, 0, rseedb.Length);
}
seedb = buff.ToArray();
buff.Dispose();
}
RNGCryptoServiceProvider CSP = new RNGCryptoServiceProvider();
HMACMD5 hmacmd5 = new HMACMD5(seedb);
HMACSHA512 hmacsha512 = new HMACSHA512(seedb);
CSP.GetNonZeroBytes(bytes_t);
byte[] md5 = hmacmd5.ComputeHash(bytes_t, 0, bytes_t.Length), sha512 = hmacsha512.ComputeHash(bytes_t, 0, bytes_t.Length);
CSP.Dispose();
hmacmd5.Dispose();
hmacsha512.Dispose();
long md5l = md5.LongLength, sha512l = sha512.LongLength;
// for (int i = 0, l = bytes_t.Length, pos = 0; i < l; i++)
Extensions.ParallelFor(0, bytes_t.LongLength, i =>
{
long posmd5 = i % md5l, possha512 = i % sha512l;
bytes_t[i] ^= md5[posmd5];
bytes_t[i] ^= sha512[possha512];
});
md5 = null;
sha512 = null;
}
Extensions.ParallelFor(0, bytes_t.LongLength, i =>
{
long pos = i % 8;
lock (bytes)
{
bytes[pos] ^= bytes_t[i];
}
});
bytes_t = null;
}
ulong modules = Convert.ToUInt64(Seed) ^ BitConverter.ToUInt64(bytes, 0), modules_x = 0, modules_t = 0, modules_xt = 0;
modules_x = modules_a[0] ^ modules_a[1] ^ modules_a[2] ^ modules_a[3];
modules_t = modules_x >> 1;
modules_t = modules_x % modules_t;
modules_t = modules_x ^ modules_t;
ticks[1] ^= ticks[3];
modules_xt = ticks[1] % modules_t;
modules = modules ^ modules_t ^ modules_xt;
Seed = modules;
}
{
RNGCryptoServiceProvider CSP = new RNGCryptoServiceProvider();
CSP.GetNonZeroBytes(seedArr);
CSP.Dispose();
byte[] bytes = BitConverter.GetBytes(Seed);
Extensions.ParallelFor(0, seedArr.LongLength, i =>
{
long pos = i % 8;
lock (seedArr)
{
seedArr[i] ^= bytes[pos];
}
});
}
Seed = 0;
}
private static byte GetByte()
{
byte retbyte;
retbyte = seedArr[next]; // Здесь System.IndexOutOfRangeException
next++;
return retbyte;
}
public static byte[] NextBytes(ulong count = 1)
{
byte[] bytes = new byte[count];
// for (int i = 0; i < count; i++)
Extensions.ParallelFor(0, bytes.LongLength, i =>
{
byte lbyte = GetByte();
bytes[i] = lbyte;
});
return bytes;
}
}Решение задачи: «Многопоточный геттер System.IndexOutOfRangeException»
textual
Листинг программы
Timer frequency as ticks per microsecond: 2343835000000 Timer is high-resolution: True Max parallel threads pass: 4 Serial 1Mb byte array, microseconds: 1375 Parallel 1Mb byte array, microseconds: 3253 Serial 2Mb byte array, microseconds: 2799 Parallel 2Mb byte array, microseconds: 7084 Serial 10Mb byte array, microseconds: 14196 Parallel 10Mb byte array, microseconds: 33382 Serial 18Mb byte array, microseconds: 25609 Parallel 18Mb byte array, microseconds: 61043 Serial 26Mb byte array, microseconds: 36987 Parallel 26Mb byte array, microseconds: 85168 Serial 34Mb byte array, microseconds: 48284 Parallel 34Mb byte array, microseconds: 113083 Serial 42Mb byte array, microseconds: 59928 Parallel 42Mb byte array, microseconds: 140026 Serial 50Mb byte array, microseconds: 71676 Parallel 50Mb byte array, microseconds: 166940 Serial 58Mb byte array, microseconds: 84363 Parallel 58Mb byte array, microseconds: 194119 Serial 66Mb byte array, microseconds: 94159 Parallel 66Mb byte array, microseconds: 220923 Serial 74Mb byte array, microseconds: 105542 Parallel 74Mb byte array, microseconds: 244599 Serial 82Mb byte array, microseconds: 116878 Parallel 82Mb byte array, microseconds: 277487 Serial 90Mb byte array, microseconds: 128088 Parallel 90Mb byte array, microseconds: 297518 Serial 98Mb byte array, microseconds: 139974 Parallel 98Mb byte array, microseconds: 330158 Serial 106Mb byte array, microseconds: 151253 Parallel 106Mb byte array, microseconds: 356841 Serial 114Mb byte array, microseconds: 161735 Parallel 114Mb byte array, microseconds: 396256 Serial 122Mb byte array, microseconds: 173373 Parallel 122Mb byte array, microseconds: 413497 Serial 130Mb byte array, microseconds: 185386 Parallel 130Mb byte array, microseconds: 439991 Serial 138Mb byte array, microseconds: 197546 Parallel 138Mb byte array, microseconds: 464581 Serial 146Mb byte array, microseconds: 209185 Parallel 146Mb byte array, microseconds: 501030 Serial 154Mb byte array, microseconds: 220108 Parallel 154Mb byte array, microseconds: 535607 Serial 162Mb byte array, microseconds: 232093 Parallel 162Mb byte array, microseconds: 559694 Serial 170Mb byte array, microseconds: 242831 Parallel 170Mb byte array, microseconds: 592954 Serial 178Mb byte array, microseconds: 255106 Parallel 178Mb byte array, microseconds: 630598 Serial 186Mb byte array, microseconds: 272178 Parallel 186Mb byte array, microseconds: 797705 Serial 194Mb byte array, microseconds: 275468 Parallel 194Mb byte array, microseconds: 782837 Serial 202Mb byte array, microseconds: 286021 Parallel 202Mb byte array, microseconds: 829967 Serial 210Mb byte array, microseconds: 298365 Parallel 210Mb byte array, microseconds: 823702 Serial 218Mb byte array, microseconds: 311791 Parallel 218Mb byte array, microseconds: 753300 Serial 226Mb byte array, microseconds: 327196 Parallel 226Mb byte array, microseconds: 786166 Serial 234Mb byte array, microseconds: 333410 Parallel 234Mb byte array, microseconds: 809886 Serial 242Mb byte array, microseconds: 352284 Parallel 242Mb byte array, microseconds: 845802 Serial 250Mb byte array, microseconds: 358615 Parallel 250Mb byte array, microseconds: 897478 Serial 258Mb byte array, microseconds: 373060 Parallel 258Mb byte array, microseconds: 894993