Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

class final SomeName {

  private volatile String string = "";
  private final Map<String, String> map = new HashMap<>();

  public SomeName() {
    map.put("1", "value1");
    map.put("2", "value2");
  }

  public String getLength() {
    return string.length();
  }

  public String getFromMap(String key) {
    return map.get(key);
  }

  public void update(String newString) {
     string = newString;
  }

}


касательно этих двух полей, вроде все потокобезопасно в этом классе?
2 окт 19, 18:25    [21985279]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
asv79
Member

Откуда: Тверь
Сообщений: 2735
rabiter
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

[src java]
class final SomeName {

private volatile String string = "";

а ты знаешь что класс String имутабелен и является сам по себе потокобезопасным?
рано тебе еще в многопоточку дядя
java core нужно подучить,я как раз тесты сделал,если хочешь будешь первым пациентом)))
2 окт 19, 18:59    [21985325]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
asv79,

Мне кажется, что тут больше вопрос к Map.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5 - по JMM да, потокобезопасно.
2 окт 19, 19:07    [21985332]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
asv79
rabiter
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

[src java]
class final SomeName {

private volatile String string = "";

а ты знаешь что класс String имутабелен и является сам по себе потокобезопасным?
рано тебе еще в многопоточку дядя
java core нужно подучить,я как раз тесты сделал,если хочешь будешь первым пациентом)))


уважаемый, пню понятно, что String иммутабельный, я для примера его и привел (в реальном примере у меня свой иммутабельный класс на его месте).
2 окт 19, 19:12    [21985339]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
Lelouch
asv79,

Мне кажется, что тут больше вопрос к Map.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5 - по JMM да, потокобезопасно.


да, вопрос больше про мап, да я что-то перегорелся.
вроде правильно публикую, так что все должно быть ок. Спасибо!
2 окт 19, 19:14    [21985344]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
asv79
rabiter
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

[src java]
class final SomeName {

private volatile String string = "";

а ты знаешь что класс String имутабелен и является сам по себе потокобезопасным?
рано тебе еще в многопоточку дядя
java core нужно подучить,я как раз тесты сделал,если хочешь будешь первым пациентом)))


не ну вот откуда такие как ты лезут вообще? что за манера? ужас просто
2 окт 19, 19:16    [21985345]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
asv79
Member

Откуда: Тверь
Сообщений: 2735
rabiter

не ну вот откуда такие как ты лезут вообще? что за манера? ужас просто

private volatile String string = "";
  private final Map<String, String> map = new HashMap<>();

вот твой код
вот твой вопрос
@касательно этих двух полей, вроде все потокобезопасно в этом классе?

что еще ты ожидал услышать
2 окт 19, 19:36    [21985356]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
asv79
rabiter
не ну вот откуда такие как ты лезут вообще? что за манера? ужас просто

private volatile String string = "";
  private final Map<String, String> map = new HashMap<>();

вот твой код
вот твой вопрос
@касательно этих двух полей, вроде все потокобезопасно в этом классе?

что еще ты ожидал услышать


ну ладно ладно, не обижайся! просто как я сюда не зайду, все что угодно, но не по делу!

так вот, там масса всего может быть непотокобезопасно. Например, если бы я map заполнял в конструкторе из внешней мапы, которая пришла бы параметром в конструктор. Или вообще, если бы по ссылке ее в конструкторе присвоил! или если бы у меня this из конструктора утекло! Или volatile бы у string не поставил. Вообщем вариантов накосячить тьма!
Я же с многопоточкой сталкиваюсь редко (энтерпрайз, все уже синхронизировано до нас). Конечно java concurrency in practice читал пару раз, но за неиспользованностью ньансы забываются! остается только тревожность и постоянная настороженность со всем, что касается многопоточки. А вы по двум строчкам диагноз ставите! Ет самое того, не надо так
2 окт 19, 19:49    [21985364]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
asv79
Member

Откуда: Тверь
Сообщений: 2735
rabiter


ну ладно ладно, не обижайся! просто как я сюда не зайду, все что угодно, но не по делу!

[/quot]
а это нормально)
кому охота после рабочего дня ковыряться в чужом коде)
вот погавкаться-мы за )
2 окт 19, 19:54    [21985370]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
asv79,

ну, кстати, с HashMap не все так очевидно. Мы же не знаем, какие она там внутренние перестановки делает при get (ну на самом деле знаем, ничего она при get не делает такого). Но чисто теоретически, если поставить на место map какой-нибудь свой mutable класс, то не все уже будет так очевидно
2 окт 19, 21:51    [21985425]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
забыл ник
Member

Откуда:
Сообщений: 3062
Попахивает нарушением S из SOLID. Поля както не зависят друг от друга. Поэтому сложно сказать о потокобезопасности. Какие еще операции есть?
2 окт 19, 23:00    [21985445]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
забыл ник
Попахивает нарушением S из SOLID. Поля както не зависят друг от друга. Поэтому сложно сказать о потокобезопасности. Какие еще операции есть?


попахивает, но это для примера. Вообще я за SOLID, и ещё знаете что? Принципы питона, ну прямо то, к чему я сам пришёл, а потом прочитал их и да - все так и есть! невероятная радость)

этот класс - это просто пример, мне было интересно, потокобезопасно ли себя ведёт HashMap в таком виде, или менять на ConcurrentHashMap.

ну а string, кстати можно же volatile String заменить на AtomicReference<String> убрав volatile?
2 окт 19, 23:13    [21985450]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
rabiter,

Больше тебе ничего не надо знать по сути твоего вопроса:

https://stackoverflow.com/a/33351133/2674303

https://stackoverflow.com/a/33351133/2674303
So, multiple threads will call the fetch method, which delegates to HashMap.get() without any synchronization. HashMap is not thread-safe. Bam, end of story.


P.S. обратите внимание на автора ответа
2 окт 19, 23:22    [21985454]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
rabiter,

private volatile String string = "";


А зачем ты это вообще включил в вопрос если вопрос про HashMap?
2 окт 19, 23:24    [21985456]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
no56892
Member

Откуда:
Сообщений: 591
rabiter
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

class final SomeName {

  private volatile String string = "";
  private final Map<String, String> map = new HashMap<>();

  public SomeName() {
    map.put("1", "value1");
    map.put("2", "value2");
  }

  public String getLength() {
    return string.length();
  }

  public String getFromMap(String key) {
    return map.get(key);
  }

  public void update(String newString) {
     string = newString;
  }

}


касательно этих двух полей, вроде все потокобезопасно в этом классе?

В общем случае нет. Если инстанс SomeName расшаривается без хэппенс бефор, то нет никаких гарантий на видимость двух элементов которые добавлены в конструкторе. Если "с" то final тут роль играет больше как const. Если уж намеренно необходимо расшаривать без hb, то в мапу надо сначала класть элементы и только потом присваивать ее финал полю. Делается это либо через временную переменную, либо через анонимный класс с инстанс инициализацией {}.
2 окт 19, 23:28    [21985460]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
no56892
rabiter
Друзья, что-то я перегрелся, развейте мои страхи!

Так же безопасно (упростил, но суть такая же)?

class final SomeName {

  private volatile String string = "";
  private final Map<String, String> map = new HashMap<>();

  public SomeName() {
    map.put("1", "value1");
    map.put("2", "value2");
  }

  public String getLength() {
    return string.length();
  }

  public String getFromMap(String key) {
    return map.get(key);
  }

  public void update(String newString) {
     string = newString;
  }

}


касательно этих двух полей, вроде все потокобезопасно в этом классе?

В общем случае нет. Если инстанс SomeName расшаривается без хэппенс бефор, то нет никаких гарантий на видимость двух элементов которые добавлены в конструкторе. Если "с" то final тут роль играет больше как const. Если уж намеренно необходимо расшаривать без hb, то в мапу надо сначала класть элементы и только потом присваивать ее финал полю. Делается это либо через временную переменную, либо через анонимный класс с инстанс инициализацией {}.


Freeze для final полей вызывается после вызова конструктора, так что по идее все изменения будут видны.
2 окт 19, 23:43    [21985461]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
no56892,

https://m.habr.com/ru/post/133981/comments/#comment_4455280
А ваш комментарий относится к volatile
2 окт 19, 23:49    [21985464]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
no56892
Member

Откуда:
Сообщений: 591
Lelouch,
Дружище, ты даже не читаешь то, на что оставляешь ссылки. Посмотри повнимательней пример 17.5-1 из нее.
2 окт 19, 23:59    [21985468]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
no56892,

Посмотрел, да, freeze работает для final полей. Понятно что y не гарантируется. При чем тут пример тс?
А вы посмотрите https://shipilev.net/talks/codefest-Mar2014-jmm-pragmatics.pdf
шипилев
Если поток прочитал из final-поля ссылку на другой объект, то состояние того как минимум настолько же свежее, как и на время freeze

Слайд finals:решение

Поэтому, если в конструкторе this не утекает, как у тс, то все норм.
3 окт 19, 00:05    [21985471]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
no56892,

То есть, насколько я вижу:
- для final полей hb это завершение конструктора и чтение ссылки на созданный объект
- для volatile hb это запись->чтение
3 окт 19, 00:18    [21985476]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
chpasha
Member

Откуда:
Сообщений: 8631
questioner
обратите внимание на автора ответа
обрати внимание на пример там и тут. Там мапа модифицируется, тут readonly
3 окт 19, 00:20    [21985477]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
chpasha
questioner
обратите внимание на автора ответа
обрати внимание на пример там и тут. Там мапа модифицируется, тут readonly


А теперь прочитай что по той ссылке написано и удивись
3 окт 19, 00:39    [21985479]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
chpasha
questioner
обратите внимание на автора ответа
обрати внимание на пример там и тут. Там мапа модифицируется, тут readonly


Brian Goetz
(Also, you probably think that HashMap.get() is a pure read operation, but that's wrong too. What if the HashMap is actually a LinkedHashMap (which is a subclass of HashMap.) LinkedHashMap.get() will update the access order, which involves writing to internal data structures -- here, concurrently without synchronization. But even if get() is doing no writing, your code here is still broken.)


Так что не надо выпендриваться. Но всё что нужно знать я уже скопировал
3 окт 19, 00:41    [21985480]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
questioner,

В вашем примере put и get выполняются без синхронизации (1е чтение) и именно поэтому при вызове .get мы можем получить что угодно. Поэтому этот пример и не работает. Упоминание LinkedHashMap полезено только с точки зрения того, что без исходников мы не можем сказать, изменяет ли состояние вызов метода.
3 окт 19, 00:59    [21985481]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
no56892,

Выдержка из jls:

then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.
3 окт 19, 01:16    [21985483]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
Lelouch
questioner,

В вашем примере put и get выполняются без синхронизации (1е чтение) и именно поэтому при вызове .get мы можем получить что угодно. Поэтому этот пример и не работает. Упоминание LinkedHashMap полезено только с точки зрения того, что без исходников мы не можем сказать, изменяет ли состояние вызов метода.


А может в новой версии джавы что-то поменяется...

А зачем вообще думать о том о чем не надо думать? это такой вид онанизма?

Doug Lea(тоже не самый последний дядька если что) вообще рекомендует использовать CHM вместо HM ибо ничего ты на этом не потеряешь
3 окт 19, 01:20    [21985484]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
Brian Goetz
HashMap is not thread-safe. Bam, end of story.


ВСЁ. дальше даже думать не надо ни о чем
3 окт 19, 01:23    [21985485]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
questioner
Lelouch
questioner,

В вашем примере put и get выполняются без синхронизации (1е чтение) и именно поэтому при вызове .get мы можем получить что угодно. Поэтому этот пример и не работает. Упоминание LinkedHashMap полезено только с точки зрения того, что без исходников мы не можем сказать, изменяет ли состояние вызов метода.


А может в новой версии джавы что-то поменяется...

А зачем вообще думать о том о чем не надо думать? это такой вид онанизма?

Doug Lea(тоже не самый последний дядька если что) вообще рекомендует использовать CHM вместо HM ибо ничего ты на этом не потеряешь


Ну меня тут интересует именно спортивный интерес про jmm. С практической точки зрения я бы тоже thread safe реализацию бы использовал.
3 окт 19, 01:26    [21985486]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
Lelouch
questioner
пропущено...


А может в новой версии джавы что-то поменяется...

А зачем вообще думать о том о чем не надо думать? это такой вид онанизма?

Doug Lea(тоже не самый последний дядька если что) вообще рекомендует использовать CHM вместо HM ибо ничего ты на этом не потеряешь


Ну меня тут интересует именно спортивный интерес про jmm. С практической точки зрения я бы тоже thread safe реализацию бы использовал.


Потом же захочется в продакшене то свои знания применить... и порядок добавления будет нужен и поменяется имплементация мапы и всё свалится....
3 окт 19, 01:30    [21985488]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
Lelouch
Member

Откуда: Москва
Сообщений: 1784
questioner
Lelouch
пропущено...


Ну меня тут интересует именно спортивный интерес про jmm. С практической точки зрения я бы тоже thread safe реализацию бы использовал.


Потом же захочется в продакшене то свои знания применить... и порядок добавления будет нужен и поменяется имплементация мапы и всё свалится....


В моем случае нет, мне приходилось отлаживать гонки, так что я лучше перестрахуюсь:)
3 окт 19, 01:36    [21985490]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
Lelouch

В моем случае нет, мне приходилось отлаживать гонки, так что я лучше перестрахуюсь:)


Вообще я отвечаю на вопрос на ТСа)
3 окт 19, 08:07    [21985524]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
Вооооот! Я же говорю, мы не знаем что там внутри HashMap на чтение (вдруг там правда какие-то внутренние рычаги дергаются которые меняют state). Или, все верно, в следующих версиях что поменяется. Вообщем чисто теоретически. Поменяю-ка я на ConcurrentHashMap. Котелок-то варит еще, почувствовал неладное и пошел сюда!
3 окт 19, 14:42    [21985908]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
rabiter
Member

Откуда: SPb
Сообщений: 663
rabiter
Вооооот! Я же говорю, мы не знаем что там внутри HashMap на чтение (вдруг там правда какие-то внутренние рычаги дергаются которые меняют state). Или, все верно, в следующих версиях что поменяется. Вообщем чисто теоретически. Поменяю-ка я на ConcurrentHashMap. Котелок-то варит еще, почувствовал неладное и пошел сюда!


Кстати, для собеседования норм может быть задачка, спросить про такой пример с HashMap на чтение и посмотреть как кандидат поразмышляет (ну если вообще про многопоточку спрашивать).
3 окт 19, 14:43    [21985910]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
chpasha
Member

Откуда:
Сообщений: 8631
rabiter
Я же говорю, мы не знаем что там внутри HashMap на чтение

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

дока oracle по java 8
Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally


про LinkedHashMap дока говорит следующее:
автор
In access-ordered linked hash maps, merely querying the map with get is a structural modification.

соответственно то, о чем пишет товарищ Götz касается особой разновидности LinkedHashMap созданной с помощью соотв. конструктора в чем можно убедится в исходнике

 public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
       this.accessOrder = accessOrder;
    }

public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }


т.е. нет никакого противоречия - HashMap.get не вызывает структурных изменений, LinkedHashMap - вызывает.

rabiter
вдруг там правда какие-то внутренние рычаги дергаются которые меняют state

а вдруг в Math.random тоже какие-то внутренние рычаги дергаются которые меняют state не смотря на то, что дока утверждает обратное? А вдруг он станет потоконебезопасен в 20й версии явы?

rabiter
Поменяю-ка я на ConcurrentHashMap
это другое дело - если существует специальная потокобезопасная версия того же самого, то нет причин ее игнорировать.
3 окт 19, 15:08    [21985945]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
забыл ник
Member

Откуда:
Сообщений: 3062
chpasha

rabiter
Поменяю-ка я на ConcurrentHashMap
это другое дело - если существует специальная потокобезопасная версия того же самого, то нет причин ее игнорировать.


Возвращаемся к вопросу о том как эта мапа будет использоваться. Операции size и empty могут выдавать немного то что хотелось бы(зависит от юскейса) - в данном случае это ок
3 окт 19, 15:22    [21985954]     Ответить | Цитировать Сообщить модератору
 Re: HashMap на чтение несколькими потоками  [new]
questioner
Member

Откуда:
Сообщений: 1865
rabiter
rabiter
Вооооот! Я же говорю, мы не знаем что там внутри HashMap на чтение (вдруг там правда какие-то внутренние рычаги дергаются которые меняют state). Или, все верно, в следующих версиях что поменяется. Вообщем чисто теоретически. Поменяю-ка я на ConcurrentHashMap. Котелок-то варит еще, почувствовал неладное и пошел сюда!


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


Обычно нужно найти человека, который решает проблемы, а не ищет себе проблемы там, где их и нет.
3 окт 19, 15:40    [21985970]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / Java Ответить