Подтвердить что ты не робот

Потоковая безопасность метода BlockingQueue drainTo()

Документация BlockingQueue говорит, что массовые операции не являются потокобезопасными, хотя в нем явно не упоминается метод drainTo().

Реализация BlockingQueue потокобезопасный. Все методы очередей достигают своих эффектов, используя атомы внутренние замки или другие формы concurrency. Однако основная масса Коллекционные операции addAll, containsAll, убрать all и removeAll не обязательно выполняются если не указано иное в реализации. Так что, это возможно, например, для addAll (c) сбой (сброс исключения) после добавление только некоторых элементов в c.

Документация метода drainTo() указывает, что сбор, к которому сливаются элементы BlockingQueue, не может быть изменен поточно-безопасным способом. Но в нем ничего не говорится о том, что операция denTo() является потокобезопасной.

Удаляет все доступные элементы из эту очередь и добавляет их к данному коллекция. Эта операция может быть больше эффективнее, чем многократно очередь. Ошибка, с которой попытка добавить элементы к сбор c может привести к появлению элементов ни в одном, ни в обоих коллекции, когда ассоциированные исключение. Попытки слить очередь к себе приводит к IllegalArgumentException. Кроме того, поведение этой операции undefined, если указанная коллекция изменяется во время работы прогресс.

Итак, метод threadTo() является поточно-безопасным? Другими словами, если один поток вызвал метод drainTo() в очереди блокировки, а другой вызвал add() или put() в той же очереди, состояние очереди согласовано в конце обеих операций?

4b9b3361

Ответ 1

Я думаю, вы вводите в заблуждение термины "потокобезопасный" и "атомный". Они не означают одно и то же. Метод может быть потокобезопасным, не будучи атомарным, и может быть атомарным (для одного потока), не будучи потокобезопасным.

Thread-safe - это резиновый термин, который трудно определить без кругового движения. Согласно Goetz, хорошей рабочей моделью является то, что метод является потокобезопасным, если он "является правильным" при использовании в многопоточном контексте, поскольку он выполняется в однопоточном контексте. Каучукостность заключается в том, что правильность субъективна, если у вас нет формальной спецификации для измерения.

В отличие от этого атомы легко определить. Это просто означает, что операция либо происходит полностью, либо вообще не происходит.

Итак, ответ на ваш вопрос заключается в том, что drainTo() является потокобезопасным, но не атомарным. Это не атомно, потому что это может вызвать исключение на полпути через дренирование. Однако, по модулю, очередь будет по-прежнему находиться в согласованном состоянии, независимо от того, делали ли другие потоки в очереди в то же время.


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

Ответ 2

drainTo() является потокобезопасным в том смысле, что любая операция в очереди, которая происходит одновременно, не изменит результат и не повредит состояние очереди. В противном случае метод будет довольно бессмысленным.

Вы можете столкнуться с проблемами, если целевая коллекция (та, к которой добавлены результаты) делает что-то "умное". Но поскольку вы обычно сбрасываете очередь в коллекцию, к которой имеет доступ только один поток, это скорее теоретическая проблема.