Многопоточный доступ к LinkedList в .Net - PullRequest
4 голосов
/ 21 сентября 2011

Мне нужен связанный список, чтобы иметь возможность добавлять элементы с обеих сторон. В списке будут храниться данные, которые будут отображаться в средстве просмотра трендов. Поскольку существует огромное количество данных, мне нужно показать данные до того, как они полностью прочитаются, поэтому я хочу прочитать блок данных, который, как я знаю, уже записан, и пока я читаю этот блок, есть два потока, заполняющие стороны Коллекция:

enter image description here

Я думал об использовании LinkedList, но он говорит, что это не поддерживает этот сценарий. Какие-нибудь идеи о чем-то в Framework, которые могут мне помочь, или мне придется разрабатывать свой список с нуля?

Заранее спасибо.

РЕДАКТИРОВАТЬ: Основная идея решения состоит в том, чтобы сделать это, не блокируя что-либо, потому что я читаю часть списка, который не будет изменен при записи в других местах. Я имею в виду, что поток чтения будет читать только один фрагмент (от A до B) (раздел, который уже был написан). Когда он закончится и другие фрагменты будут полностью записаны, читатель будет читать эти фрагменты, пока авторы записывают новые данные.

См. Обновленную диаграмму:

enter image description here

Ответы [ 5 ]

2 голосов
/ 21 сентября 2011

Если вы используете .NET4, вы можете использовать два ConcurrentQueue.Один для левой стороны и один для правой стороны.

1 голос
/ 21 сентября 2011

Если я правильно понимаю, у вас есть связанный список, к которому вы добавляете данные в начале и в конце. Вы никогда не добавляете и не удаляете откуда-либо еще. В этом случае вам не нужно беспокоиться о многопоточности, поскольку другие потоки никогда не будут мешать.

Просто сделайте что-то вроде этого:

        //Everything between first and last is thread safe since 
        //the other threads only add before and after.
        LinkedListNode<object> first = myList.First;
        LinkedListNode<object> current = first;
        LinkedListNode<object> last = myList.Last;
        bool done = false;

        if (current == null) return; //empty list
        do
        {
            //do stuff
            if (current == last) done = true;
            current = current.Next;
        } while (!done && current != null);

После того, как вы закончили с этим разделом, вы можете сделать то же самое с двумя другими разделами от нового myList.First до первого и от последнего до нового myList.Last.

1 голос
/ 21 сентября 2011

Почему бы не использовать LinkedList класс. В документации сказано, что она не является поточно-ориентированной, поэтому вам нужно синхронизировать доступ к списку для себя, но вы должны делать это с любой структурой данных, доступ к которой осуществляется несколькими потоками.

Производительность должна быть тихой, хорошо вот что msdn говорит о вставке узлов в любую позицию:

LinkedList предоставляет отдельные узлы типа LinkedListNode, поэтому вставка и удаление являются операциями O (1).

Вам просто нужно заблокировать операции чтения и вставки с помощью конструкции lock.

EDIT

Хорошо, я думаю, что понимаю, что вы хотите. Вам нужен список, подобный структуре данных, которая разбита на куски элементов. Вы хотите самостоятельно писать и читать фрагменты элементов, не блокируя весь список.

Я предлагаю использовать LinkedList, содержащий ваши фрагменты данных. Сами блоки могут быть представлены в виде простого List или экземплярами LinkedList.

Вы должны заблокировать доступ к глобальному LinkedList.

Теперь ваши темы писателя заполняют один личный список из n элементов одновременно По окончании писатель блокирует LinkedList и добавляет свой личный список с элементами данных в LinkedList.

Поток читателя блокирует LinkedList, читает один кусок и снимает блокировку. Теперь он может обрабатывать n элементов данных, не блокируя их.

1 голос
/ 21 сентября 2011

Я бы порекомендовал рассмотреть другой подход с единой структурой данных для сохранения входящих данных, таким образом, вы можете поддерживать порядок сообщений входящих данных. Например, вы можете использовать очередь блокировки, в этом сообщении SO вы можете найти хороший пример Создание очереди блокировки в .NET? .

1 голос
/ 21 сентября 2011

Вы можете использовать связанный список и просто использовать обычные конструкции потоков .NET, например ключевое слово lock, для защиты доступа к списку.

Любой пользовательский список, который вы разработали, вероятно, все равно будет делать что-то подобное.

...