Потоковая безопасность метода dumpTo () BlockingQueue - PullRequest
14 голосов
/ 07 июля 2011

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

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

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

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

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

Ответы [ 2 ]

16 голосов
/ 07 июля 2011

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

Потокобезопасный - это резиновый термин, который трудно определить, не будучи круглым. Согласно Гетцу, хорошей рабочей моделью является то, что метод является поточно-ориентированным, если он «так же корректен» при использовании в многопоточном контексте, как и в однопоточном контексте. Резинность заключается в том, что правильность субъективна, если только у вас нет формальной спецификации для сравнения.

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

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


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

5 голосов
/ 07 июля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...