Атомарный способ переупорядочить ключи в ConcurrentSkipListMap / ConcurrentSkipListSet?

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

Например, нескольким потокам необходим доступ String ключи в произвольном порядке сортировки. Их строки сортируются не в соответствии с их естественным порядком, а по некоторым значениям, которые могут измениться (следовательно, пользовательские Comparator). Моей первоначальной реализацией было использование TreeSet и синхронизировать на нем. Если какой-либо из ключей необходимо переупорядочить, поток удалит ключ из карты, обновит значение сравнения и заново вставит ключ. Чтобы реализовать это, ключи являются родными Stringс, но компаратор имеет доступ к значениям. Это странное соглашение, в котором порядок ключей может меняться со временем, но поскольку измененный ключ всегда удаляется и повторно вставляется при его изменении, он, похоже, работает. (Я полагаю, это может также работать, если Strings были обернуты внутри другого объекта.)

Я недавно узнал о ConcurrentSkipListSet/ConcurrentSkipListMap реализации, которые в основном являются потокобезопасными отсортированными наборами (соответственно картам). Кажется, что теперь я могу перебирать ключи без необходимости блокировать всю структуру данных. Тем не менее, есть ли способ, которым я могу использовать их для атомарного удаления ключа и замены его другим, как операция, которую я делал выше, чтобы другие итерирующие потоки не пропускали элемент, и без необходимости использовать synchronize блоки?

Если кто-то может предложить лучшую структуру данных для этого типа операции, я тоже весь слух!

1 ответ

Решение

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

Краткий ответ: нет. Если вам нужно удалить и повторно вставить, нет никакого атомарного способа сделать это с любой коллекцией, о которой я знаю.

Тем не менее, одна возможность будет для вас повторно вставить элемент, прежде чем удалить его из списка пропуска. Это может привести к дублированию, но может быть легче обработать, чем отсутствующую запись. Вы бы заново вставили его после того, как изменили объект, чтобы он сортировался по-другому. Это предполагает, что тогда объект также будет неравным. Но если другие потоки, которые обрабатывают списки, не могут обработать дубликаты, тогда я думаю, что вы SOL.

Другие вопросы по тегам