Во-первых, меня интересует предположение в этих двух строках последовательного кода:
node.data[current++] = x;
// We have to use interlocked, to assure that we incremeent the count
// atomicalluy, because the reader could be reading it.
Interlocked.Increment(ref node.count);
Что сказать, что новое значение node.data [] зафиксировано в этой ячейке памяти? Он не хранится в энергозависимом адресе памяти и поэтому может быть кэширован, если я правильно понимаю? Не приводит ли это к «грязному» чтению? Могут быть и другие места, то же самое верно, но это сразу бросилось в глаза.
Второй многопоточный код, содержащий следующее:
Thread.Sleep(int);
... никогда не бывает хорошим знаком. Если это требуется, то код предназначен для сбоя, если это не требуется, это пустая трата. Мне бы очень хотелось, чтобы они полностью удалили этот API. Поймите, что это просьба подождать хотя бы такое количество времени. С переключением контекста вы почти наверняка будете ждать дольше, намного дольше.
В-третьих, я совершенно не понимаю, как здесь используется интерфейс блокировки. Может быть, я устал и просто упускаю суть; но я не могу найти потенциальный конфликт потоков в обоих потоках, читающих и пишущих в одну и ту же переменную? Казалось бы, единственное использование, которое я мог найти для обмена блокировками, - это изменить содержимое файла node.data [], чтобы исправить # 1 выше.
Наконец, может показаться, что реализация несколько усложнена. Я упускаю суть всего, что связано с курсором / узлом, или он делает то же самое, что и этот класс? (Примечание: я не пробовал и не думаю, что это потокобезопасно, просто пытаюсь свести на нет то, что я думаю, что вы делаете.)
class ReaderWriterQueue<T>
{
readonly AutoResetEvent _readComplete;
readonly T[] _buffer;
readonly int _maxBuffer;
int _readerPos, _writerPos;
public ReaderWriterQueue(int maxBuffer)
{
_readComplete = new AutoResetEvent(true);
_maxBuffer = maxBuffer;
_buffer = new T[_maxBuffer];
_readerPos = _writerPos = 0;
}
public int Next(int current) { return ++current == _maxBuffer ? 0 : current; }
public bool Read(ref T item)
{
if (_readerPos != _writerPos)
{
item = _buffer[_readerPos];
_readerPos = Next(_readerPos);
return true;
}
else
return false;
}
public void Write(T item)
{
int next = Next(_writerPos);
while (next == _readerPos)
_readComplete.WaitOne();
_buffer[next] = item;
_writerPos = next;
}
}
Значит, я здесь совершенно вне базы и не вижу магию в исходном классе?
Я должен признать одну вещь, я презираю Threading. Я видел, как лучшие разработчики терпят неудачу в этом. В этой статье приведен отличный пример того, как трудно правильно настроить многопоточность:
http://www.yoda.arachsys.com/csharp/singleton.html