Действительно ли безопасно получить значения от java.util. HashMap от нескольких потоков (никакая модификация)?

То, что вы печатаете, является лишь кратким представлением результата запроса.

Если вы хотите проверить статус, вы можете использовать:

requestt.status_code == requests.codes.ok

Это будет то, что вы напечатаете, просто краткое представление результата запроса.

Если вы хотите проверить статус, вы можете использовать:

requestt.status_code == requests.codes.ok

Это будет True, если код состояния - 200 (ОК), в противном случае - False. В любом случае requestt.status_code будет кодом состояния в виде целого числа.

135
задан Dave L. 19 September 2008 в 18:11
поделиться

9 ответов

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

http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html

9
ответ дан 23 November 2019 в 23:48
поделиться

Существует важное скручивание все же. Безопасно получить доступ к карте, но в целом не гарантируется, что все потоки будут видеть точно то же состояние (и таким образом оценивает) HashMap. Это могло бы произойти в многопроцессорных системах, где модификации к HashMap, сделанному одним потоком (например, тот, который заполнил его), могут находиться в том, что кэш ЦП и не будет замечен потоками, работающими на других центральных процессорах, пока операция забора памяти не будет выполнена, гарантируя когерентность кэша. Спецификация языка Java является явной на этом: решение состоит в том, чтобы получить блокировку (синхронизировался (...)), который испускает операцию забора памяти. Так, если Вы уверены, что после заполнения HashMap каждый из потоков получает ЛЮБУЮ блокировку, затем это в порядке от той точки на получить доступ к HashMap от любого потока, пока HashMap не изменяется снова.

8
ответ дан 23 November 2019 в 23:48
поделиться

http://www.docjar.com/html/api/java/util/HashMap.java.html

вот источник для HashMap. Как можно сказать, нет абсолютно никакой блокировки / взаимоисключающий код там.

Это означает что, в то время как хорошо для чтения из HashMap в многопоточной ситуации я определенно использовал бы ConcurrentHashMap, если бы было несколько записей.

интересный Whats то, что и HashTable.NET и Dictionary< K, V> создали в коде синхронизации.

0
ответ дан 23 November 2019 в 23:48
поделиться

Предупредите, что даже в однопоточном коде, заменяя ConcurrentHashMap HashMap может не быть безопасным. ConcurrentHashMap запрещает пустой указатель как ключ или значение. HashMap не запрещает им (не спрашивайте).

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

Тем не менее, если Вы не делаете ничего иного, параллельные чтения от HashMap безопасны.

[Редактирование: "параллельными чтениями", я подразумеваю, что нет также параллельных модификаций.

Другие ответы объясняют, как гарантировать это. Один путь состоит в том, чтобы сделать карту неизменной, но это не необходимо. Например, модель памяти JSR133 явно определяет запуск потока, чтобы быть синхронизируемым действием, означая, что изменения сделали в потоке, прежде чем это запустится, поток B видимы в потоке B.

Мое намерение не состоит в том, чтобы противоречить тем более подробным ответам о Модели памяти Java. Этот ответ предназначается, чтобы указать что даже кроме проблем параллелизма, существует по крайней мере одно различие API между ConcurrentHashMap и HashMap, который мог погубить даже однопоточную программу, которая заменила один другим.]

1
ответ дан 23 November 2019 в 23:48
поделиться

Чтения безопасны от точки зрения синхронизации, но не точки зрения памяти. Это - что-то, что широко неправильно понято среди Java-разработчиков включая здесь на Stackoverflow. (Наблюдайте оценку этот ответ для доказательства.)

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

См. статья Brian Goetz о новой Модели памяти Java для деталей.

35
ответ дан 23 November 2019 в 23:48
поделиться

У Jeremy Manson, бога когда дело доходит до Модели памяти Java, есть три блога части по этой теме - потому что в сущности Вы задаете вопрос, "Это безопасный получить доступ к неизменному HashMap" - ответ на это - да. Но необходимо ответить на предикат на тот вопрос, который является - "Мой неизменный HashMap". Ответ мог бы удивить Вас - Java имеет относительно сложный подшипник для определения неизменности.

Для большего количества информации о теме, считайте сообщения в блоге Jeremy:

Часть 1 на Неизменности в Java: http://jeremymanson.blogspot.com/2008/04/immutability-in-java.html

Часть 2 на Неизменности в Java: http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-2.html

Часть 3 на Неизменности в Java: http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-3.html

70
ответ дан 23 November 2019 в 23:48
поделиться

После немного большего количества взгляда я нашел это в документ Java (шахта акцента):

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

Это, кажется, подразумевает, что будет безопасно, принятие обратного из оператора там верно.

9
ответ дан 23 November 2019 в 23:48
поделиться

Этот вопрос рассмотрен в "Параллелизме Java Brian Goetz в практике" книга (Список 16.8, страница 350):

@ThreadSafe
public class SafeStates {
    private final Map<String, String> states;

    public SafeStates() {
        states = new HashMap<String, String>();
        states.put("alaska", "AK");
        states.put("alabama", "AL");
        ...
        states.put("wyoming", "WY");
    }

    public String getAbbreviation(String s) {
        return states.get(s);
    }
}

С тех пор states объявляется как final, и его инициализация выполняется в рамках конструктора класса владельца, любой поток, кто более поздние чтения эта карта, как гарантируют, будут видеть его по состоянию на время концы конструктора, если никакой другой поток не попытается изменить содержание карты.

0
ответ дан 23 November 2019 в 23:48
поделиться

So the scenario you described is that you need to put a bunch of data into a Map, then when you're done populating it you treat it as immutable. One approach that is "safe" (meaning you're enforcing that it really is treated as immutable) is to replace the reference with Collections.unmodifiableMap(originalMap) when you're ready to make it immutable.

For an example of how badly maps can fail if used concurrently, and the suggested workaround I mentioned, check out this bug parade entry: bug_id=6423457

3
ответ дан 23 November 2019 в 23:48
поделиться