powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / больше DCL
52 сообщений из 52, показаны все 3 страниц
больше DCL
    #39391527
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Корректен ли код?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
import java.util.HashMap;
import java.util.Map;

// REVIEW
public abstract class Digest {
    private Map<String, byte[]> cache = new HashMap<>();

    public byte[] digest(String input) {
        byte[] result = cache.get(input);
        if (result == null) {
            synchronized (cache) {
                result = cache.get(input);
                if (result == null) {
                    result = doDigest(input);
                    cache.put(input, result);
                }
            }
        }
        return result;
    }

    protected abstract byte[] doDigest(String input);
}



корректен ли код?

Если нет, то поможет ли volatile пометить cache ?
Просто никогда не думал насчёт того, что если мы видим корректное visibility ссылки на объект - распространяется ли это на те объекты, на которые он ссылается(композирует, аггрегирует)?
...
Рейтинг: 0 / 0
больше DCL
    #39391544
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerкорректен ли код?

Не совсем. Чтение может происходит параллельно с записью, что чревато.

questionerЕсли нет, то поможет ли volatile пометить cache ?

Устал уже что ли? volatile здесь только влияет на ссылку cache. А ссылка эта нигде в коде не меняется. Можно final воткнуть.

questionerПросто никогда не думал насчёт того, что если мы видим корректное visibility ссылки на объект - распространяется ли это на те объекты, на которые он ссылается(композирует, аггрегирует)?
Нет, не распространяется.
...
Рейтинг: 0 / 0
больше DCL
    #39391654
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczquestionerкорректен ли код?

Не совсем. Чтение может происходит параллельно с записью, что чревато.

Что прочитаем что-то не то?
Можно сказать что-то более конкретное, чем непредсказуемое поведение?

BlazkowiczУстал уже что ли? volatile здесь только влияет на ссылку cache. А ссылка эта нигде в коде не меняется. Можно final воткнуть.

Я понимаю, что final он же volatile. Но конкретно в этом коде это повлияет разве как-то? или только на возможное расширение класса. Ну то есть разве может кто-то увидеть null ссылку на cache ?


Правильно ли, что если не использовать другую коллекцию, то можно использовать например ReadWriteLock?
...
Рейтинг: 0 / 0
больше DCL
    #39391696
Фотография fixxer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это не вопрос ли из анкеты в ваканси Java Developer в Яндекс?
...
Рейтинг: 0 / 0
больше DCL
    #39391806
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
fixxerЭто не вопрос ли из анкеты в ваканси Java Developer в Яндекс?

Я слышал кстати уже такую версию. Возможно собеседующий ходил в яндекс когда-то)
...
Рейтинг: 0 / 0
больше DCL
    #39391831
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
немного перефразирую второй вопрос

если мы не используем volatile/final могут ли быть проблемы с видимостью cache ?

ведь получается, что мы сетаем его в конструкторе(думаю это эквивалентно текущей записи).

а использовать метод мы можем только после того ссылка создалась.

Есть на такой случай HB ?
...
Рейтинг: 0 / 0
больше DCL
    #39391901
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Тут две проблемы.
1. При удачном стечении обстоятельств, после публикации экземпляра наследника можно схватить NPE на том, что cache все еще null, а digest уже вызвали.
2. Недавно пролетал опрос на то, что бывает с HashMap при многопоточном использовании.
...
Рейтинг: 0 / 0
больше DCL
    #39391913
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,

Тут две проблемы.
1. При удачном стечении обстоятельств, после публикации экземпляра наследника можно схватить NPE на том, что cache все еще null, а digest уже вызвали.
2. Недавно пролетал опрос на то, что бывает с HashMap при многопоточном использовании.


volatile я так понимаю спасёт нас от 1 пункта.

по поводу второго мы там ни о чем не договорились, отличного от того, что поведение непредсказуемо
...
Рейтинг: 0 / 0
больше DCL
    #39391927
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerпо поводу второго мы там ни о чем не договорились, отличного от того, что поведение непредсказуемо
А этого достаточно, чтоб так не делать.
...
Рейтинг: 0 / 0
больше DCL
    #39391984
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestionerпо поводу второго мы там ни о чем не договорились, отличного от того, что поведение непредсказуемо
А этого достаточно, чтоб так не делать.

Пусть я собеседую:

Ок, разобрались, что лучше использовать CHM, но допустим по каким-то причинам мы этого сделать не можем, как сделать корректным без CHM ?
...
Рейтинг: 0 / 0
больше DCL
    #39391999
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerПравильно ли, что если не использовать другую коллекцию, то можно использовать например ReadWriteLock?
Да.
...
Рейтинг: 0 / 0
больше DCL
    #39392002
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerесли мы не используем volatile/final могут ли быть проблемы с видимостью cache ?

Надо освежить что там в JMM пишут по поводу конструктора и безопасных публикаций. То есть, если у тебя из конструктора, утекает ссылка на объект, да ещё и в другой поток, то он может увидеть null.

questionerведь получается, что мы сетаем его в конструкторе(думаю это эквивалентно текущей записи).

Да, но вопрос в том, чем ты гарантируешь что другой поток не увидит объект во время выполнения конструктора?

questionerа использовать метод мы можем только после того ссылка создалась.

Тут чувствуется некоторое непонимание в вопросе. Нет никакого "ссылка создалась". Ссылку на объект можно получить до того как закончит выполнение конструктор.
...
Рейтинг: 0 / 0
больше DCL
    #39392005
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев 1. При удачном стечении обстоятельств, после публикации экземпляра наследника можно схватить NPE на том, что cache все еще null, а digest уже вызвали.

Из наследника можно получить null даже если там будет final. Эта другая проблема.

Сергей Арсеньев2. Недавно пролетал опрос на то, что бывает с HashMap при многопоточном использовании.
Так он же и спрашивал. Теперь решил по второму кругу.
...
Рейтинг: 0 / 0
больше DCL
    #39392006
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczИз наследника можно получить null даже если там будет final. Эта другая проблема.

Не-е, гоню. Это в родительском классе можно получить null в final поле. В любом случае родители и наследники, это не единственный способ сделать публикацию объекта не безопасной.
...
Рейтинг: 0 / 0
больше DCL
    #39392028
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczquestionerПравильно ли, что если не использовать другую коллекцию, то можно использовать например ReadWriteLock?
Да.

прошу оценить критическим взглядом:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
public abstract class Digest {

    private final ReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock readLock = rwl.readLock();
    private final Lock writeLock = rwl.writeLock();

    private Map<String, byte[]> cache = new HashMap<>();

    public byte[] digest(String input) {
        byte[] result = null;
        readLock.lock();
        try {
            result = cache.get(input);
        } finally {
            readLock.unlock();
        }
        if (result == null) {
            writeLock.lock();
            try {
                result = cache.get(input);
                if (result == null) {
                    result = doDigest(input);
                    cache.put(input, result);
                }
            } finally {
                writeLock.unlock();
            }
        }

        return result;
    }

    protected abstract byte[] doDigest(String input);
}
...
Рейтинг: 0 / 0
больше DCL
    #39392035
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczquestionerесли мы не используем volatile/final могут ли быть проблемы с видимостью cache ?

Надо освежить что там в JMM пишут по поводу конструктора и безопасных публикаций. То есть, если у тебя из конструктора, утекает ссылка на объект, да ещё и в другой поток, то он может увидеть null.

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

Да, но вопрос в том, чем ты гарантируешь что другой поток не увидит объект во время выполнения конструктора?


А как можно запустить конструирование одного и того же объекта из разных тредов?
Я на самом деле не представляю другого способа кроме как утекания ссылки из конструктора. В нашем конкретно коде такое возможно?

questionerа использовать метод мы можем только после того ссылка создалась.

BlazkowiczТут чувствуется некоторое непонимание в вопросе. Нет никакого "ссылка создалась". Ссылку на объект можно получить до того как закончит выполнение конструктор.


Кроме утекания из конструктора ещё есть какие-то варианты такого?
...
Рейтинг: 0 / 0
больше DCL
    #39392044
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczBlazkowiczИз наследника можно получить null даже если там будет final. Эта другая проблема.

Не-е, гоню. Это в родительском классе можно получить null в final поле. В любом случае родители и наследники, это не единственный способ сделать публикацию объекта не безопасной.

Надо бы отдельно это обсудить) может ссылку какую выдадите?
...
Рейтинг: 0 / 0
больше DCL
    #39392111
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz В любом случае родители и наследники, это не единственный способ сделать публикацию объекта не безопасной.
Наследник был упомянут, токма по причине абстрактности класса.
final как бы гарантирует что ссылка на экземпляр раньше времени (заполнения final) не утечет.
Другое дело, что HashMap не очень то хороший cache, особенно в свете многопоточности.
Есть же всякие в Guave и у Apache реализации.
...
Рейтинг: 0 / 0
больше DCL
    #39392149
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевBlazkowicz В любом случае родители и наследники, это не единственный способ сделать публикацию объекта не безопасной.
Наследник был упомянут, токма по причине абстрактности класса.
final как бы гарантирует что ссылка на экземпляр раньше времени (заполнения final) не утечет.
Другое дело, что HashMap не очень то хороший cache, особенно в свете многопоточности.
Есть же всякие в Guave и у Apache реализации.

Приватное поле недоступно наследнику же.

Не понял как final с утеканием связан. Может пример?


Ну это понятно. что есть нормальные протестированные кеши, это не практический вопрос, исключительно в образовательных целях рассматривается
...
Рейтинг: 0 / 0
больше DCL
    #39392187
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerНу это понятно. что есть нормальные протестированные кеши, это не практический вопрос, исключительно в образовательных целях рассматривается
Чисто в образовательных целях надо читать Java Memory Model. Там есть ссылочка на документик в котором описывается как jvm инициализирует экземпляр класса в каком порядке и когда отпускается блокировочка не позволяющая увидеть ссылку раньше некоторого события. Так вот final поля они до, а не final и цепочка конструкторов после.
В связи с чем есть теоретическая возможность (и та скорее всего не для x86) что кто-то увидит ссылку на экземпляр наследника, когда cache еще не до конца проинициализирован. После чего вызов instance.digest(), который у Вас первым делом пытался сделать cache.get() будет слегка удивлен.

Если я правильно понимаю (хотя скорее ошибаюсь), то и вызов readLock.lock(); из другого потока (не того, в котором происходила инициализация instance) не устанавливает h-b грань (ибо в нем инициализации то не происходило).
...
Рейтинг: 0 / 0
больше DCL
    #39392211
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
больше DCL
    #39392275
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Usmanquestioner,

https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java

Это к чему вообще?
...
Рейтинг: 0 / 0
больше DCL
    #39392281
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerЭто к чему вообще?К 1-му посту
...
Рейтинг: 0 / 0
больше DCL
    #39392303
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
UsmanquestionerЭто к чему вообще?К 1-му посту

Если честно, я не понял, проясните.

В примере с вики там волатильная ссылка, но там и проверяется на null эта же ссылка, в нашем случае не так
...
Рейтинг: 0 / 0
больше DCL
    #39392315
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerВ примере с вики там волатильная ссылкаВ Вашем случае переменную cache необходимо сделать volatile questionerно там и проверяется на null эта же ссылка, в нашем случае не такв этом необходимости нет, т.к. cache сразу инициализируется.questionerкорректен ли код?думаю - да, если добавить volatile .questioner
Код: java
1.
byte[] result = cache.get(input);

По поводу работы HashMap в мультипоточной среде. (см. Note that this implementation is not synchronized )
...
Рейтинг: 0 / 0
больше DCL
    #39392333
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UsmanВ Вашем случае переменную cache необходимо сделать volatile
Еще лучше final, если потом менять не предполагается,
И HashMap заменить на ConcurrentHashMap
И вместо объектов хранить обертку позволяющую заменить себя на WeakReference
И процедуру прочистки, сначала ref на weak (по прошествии времени по установленному механизму вытеснения).
Затем и удаление ключа, если weak обнулился.
...
Рейтинг: 0 / 0
больше DCL
    #39392357
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
UsmanquestionerВ примере с вики там волатильная ссылкаВ Вашем случае переменную cache необходимо сделать volatile questionerно там и проверяется на null эта же ссылка, в нашем случае не такв этом необходимости нет, т.к. cache сразу инициализируется.questionerкорректен ли код?думаю - да, если добавить volatile .questioner
Код: java
1.
byte[] result = cache.get(input);

По поводу работы HashMap в мультипоточной среде. (см. Note that this implementation is not synchronized )

по поводу "будет работать" http://stackoverflow.com/a/33351133/2674303 Вы всё ещё уверены?

Вот почему нужен или не нужен этот volatile/final я ничего не понял. Почему "в этом необходимости" ?
...
Рейтинг: 0 / 0
больше DCL
    #39392359
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевUsmanВ Вашем случае переменную cache необходимо сделать volatile
Еще лучше final, если потом менять не предполагается,
И HashMap заменить на ConcurrentHashMap
И вместо объектов хранить обертку позволяющую заменить себя на WeakReference
И процедуру прочистки, сначала ref на weak (по прошествии времени по установленному механизму вытеснения).
Затем и удаление ключа, если weak обнулился.

Вот не знаю чего-то у меня чувство, что никакого эффекта volatile не принесёт)

Прям ConcurrentWeakHashMap описали)
...
Рейтинг: 0 / 0
больше DCL
    #39392361
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,
Brian GoetzHashMap is not thread-safe. Bam, end of story.
Вам об этом уже вторую тему пишут, только Гётц достаточный авторитет?
Но про чтение это он ловко.
...
Рейтинг: 0 / 0
больше DCL
    #39392363
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczquestioner,
Brian GoetzHashMap is not thread-safe. Bam, end of story.
Вам об этом уже вторую тему пишут, только Гётц достаточный авторитет?
Но про чтение это он ловко.

Ну так спрашиваю не потому, что я такой любознательный. Меня лично об этом на собеседовании спрашивали. И ответ что типа не надо использовать не подготовленные мапы в однопоточной среде ибо просто не надо так делать, они задизайнены под один поток на него не подействовали. Хотел узнать что будет конкретно в каждом конкретном случае.
...
Рейтинг: 0 / 0
больше DCL
    #39392364
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerВ нашем конкретно коде такое возможно?
- Вот это код говно?
- Да, говно.
- Но почему он говно?
- Потому что, вот тут может сломаться и тут может сломаться.
- Но ведь, у в этом коде этого нет, и того тоже нет.
- А если что-то в этом коде поменять, то он сломается. Поэтому код говно.

Мы уже вторую тему пытаемся узнать как будет работать не жиснеспособный код. Для каких научных изысканий это вдруг понадобилось?
...
Рейтинг: 0 / 0
больше DCL
    #39392365
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczquestionerВ нашем конкретно коде такое возможно?
- Вот это код говно?
- Да, говно.
- Но почему он говно?
- Потому что, вот тут может сломаться и тут может сломаться.
- Но ведь, у в этом коде этого нет, и того тоже нет.
- А если что-то в этом коде поменять, то он сломается. Поэтому код говно.

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

Ну вообще наверное полезно понимать, что происходит при написании кода, на что можно полагаться, а на что нет
...
Рейтинг: 0 / 0
больше DCL
    #39392366
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerХотел узнать что будет конкретно в каждом конкретном случае.
Конкретно будет любая неведомая уита - бесконечные циклы, NPE, ненахождение значений, которые там есть и вообще любое непредсказуемое поведение, которое зависит от версии Java. Потому как Java API гарантирует определенное поведение при правильном использовании. А при не правильном использовании они никак не гарантирует что сегодня оно будет так ломаться, а завтра иначе.
...
Рейтинг: 0 / 0
больше DCL
    #39392368
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerНу вообще наверное полезно понимать, что происходит при написании кода, на что можно полагаться, а на что нет
Можно полагаться на документацию. Нельзя полагаться на то чего в документации нет.
...
Рейтинг: 0 / 0
больше DCL
    #39392370
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczquestionerХотел узнать что будет конкретно в каждом конкретном случае.
Конкретно будет любая неведомая уита - бесконечные циклы, NPE, ненахождение значений, которые там есть и вообще любое непредсказуемое поведение, которое зависит от версии Java. Потому как Java API гарантирует определенное поведение при правильном использовании. А при не правильном использовании они никак не гарантирует что сегодня оно будет так ломаться, а завтра иначе.

ну ок, в эту сторону предлагаю не копать.

Но вот в решении с ReadWriteLock надо volatile/final у поля или нет?
Если да, то почему?

Решение работоспособно вообще или нет?
...
Рейтинг: 0 / 0
больше DCL
    #39392397
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerНо вот в решении с ReadWriteLock надо volatile/final у поля или нет?
Если да, то почему?

Не надо, но при условии, что доступ к этой переменной идет только в одном потоке и все доступы синхронизированы на одном локе
...
Рейтинг: 0 / 0
больше DCL
    #39392399
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник в одном потоке

в одном объекте
...
Рейтинг: 0 / 0
больше DCL
    #39392408
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл никquestionerНо вот в решении с ReadWriteLock надо volatile/final у поля или нет?
Если да, то почему?

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

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
public abstract class Digest {

    private final ReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock readLock = rwl.readLock();
    private final Lock writeLock = rwl.writeLock();

    private Map<String, byte[]> cache = new HashMap<>();

    public byte[] digest(String input) {
        byte[] result = null;
        readLock.lock();
        try {
            result = cache.get(input);
        } finally {
            readLock.unlock();
        }
        if (result == null) {
            writeLock.lock();
            try {
                result = cache.get(input);
                if (result == null) {
                    result = doDigest(input);
                    cache.put(input, result);
                }
            } finally {
                writeLock.unlock();
            }
        }

        return result;
    }

    protected abstract byte[] doDigest(String input);
}



код отвечает вашим требованиям?
...
Рейтинг: 0 / 0
больше DCL
    #39392417
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerНо вот в решении с ReadWriteLock надо volatile/final у поля или нет?
Если да, то почему?

Решение работоспособно вообще или нет?
Точнее в решении с volatile/final не нужен ReadWriteLock (он дороже к тому же).
И то и другое гарантирует, что установится h-b отношение. Говорящее о том, что все что должно было быть сделано раньше в этом потоке до действия a будет видно и в других потоках если в нем увидели результат a.
Другими словами если в переменную volatile записали что-то, что должно быть по программе раньше этой записи (отработал конструктор). То другой поток получит эту ссылку только после отработавшего конструктора.
Поскольку другие потоки не увидят никаких действий, которые происходят в этом фрагменте
Код: java
1.
2.
3.
4.
5.
6.
 readLock.lock();
        try {
            result = cache.get(input);
        } finally {
            readLock.unlock();
        }


То никакого смысла в созданных h-b отношениях нет.
Вот если б new HashMap<>(); дергал readLock.lock(); тогда да.
Но на практике это увидеть не реально.
Нет - по причине HashMap.
...
Рейтинг: 0 / 0
больше DCL
    #39392421
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerВы всё ещё уверены?
Да (:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
package ru.sql.java;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;

public abstract class Digest {
    
    private Map<String, byte[]> cache = new HashMap<>(); // без volatile !!!

    public byte[] digest(String input) {
        byte[] result = cache.get(input);
        if (result == null) {
            synchronized (cache) {
                result = cache.get(input);
                if (result == null) {
                    result = doDigest(input);
                    cache.put(input, result);
                }
            }
        } else {
            // если key == value, тогда OK
            if (!ArrayUtils.isEquals(input.getBytes(), result)) {
                System.out.printf("%s != %d%n", input, result[0]); // FAIL, если get() выдал не то, что нужно
            }
        }
        return result;
    }

    protected abstract byte[] doDigest(String input);
    
    static long key = 0;

    public static void main(String[] args) {
        Digest digest = new Digest() {
            @Override
            protected byte[] doDigest(String input) {
                return input.getBytes();
            }
        };
        
        Runnable r = () -> digest.digest(String.valueOf(++key));
        
        List<Thread> tl;
        
        int times = 5000;
        
        // выполняется put() (т.к. cache еще пуст)
        
        key = 0;
        tl = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            tl.add(new Thread(r));
        }
        for (Thread t: tl) {
            t.start();
        }
        
        // теперь get() возвращает неNULLевое значение
        
        key = 0;
        tl = new ArrayList<>();
        for (int i = 0; i < times; i++) {
            tl.add(new Thread(r));
        }
        for (Thread t: tl) {
            t.start();
        }
    }
}

...
Рейтинг: 0 / 0
больше DCL
    #39392474
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевquestionerНо вот в решении с ReadWriteLock надо volatile/final у поля или нет?
Если да, то почему?

Решение работоспособно вообще или нет?
Точнее в решении с volatile/final не нужен ReadWriteLock (он дороже к тому же).
И то и другое гарантирует, что установится h-b отношение. Говорящее о том, что все что должно было быть сделано раньше в этом потоке до действия a будет видно и в других потоках если в нем увидели результат a.
Другими словами если в переменную volatile записали что-то, что должно быть по программе раньше этой записи (отработал конструктор). То другой поток получит эту ссылку только после отработавшего конструктора.
Поскольку другие потоки не увидят никаких действий, которые происходят в этом фрагменте
Код: java
1.
2.
3.
4.
5.
6.
 readLock.lock();
        try {
            result = cache.get(input);
        } finally {
            readLock.unlock();
        }


То никакого смысла в созданных h-b отношениях нет.
Вот если б new HashMap<>(); дергал readLock.lock(); тогда да.
Но на практике это увидеть не реально.
Нет - по причине HashMap.

А решение с volatile это какое точно? Код можно?

Вас не смущают параллельные чтения и записи?
...
Рейтинг: 0 / 0
больше DCL
    #39392577
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerА решение с volatile это какое точно? Код можно?

Вас не смущают параллельные чтения и записи?
Вам про Фому, Вы про Ерёму.

JIT компилятору (да и процессору если умеет) разрешен out of order execution.
Другими словами встретив
Код: java
1.
 private Map<String, byte[]> cache = new HashMap<>();


Они имеют право записать в переменную cache адрес отведенного под HashMap участка памяти и пойти выполнять код дальше, а конструктор отложить на потом.
Однако, если встретится обращение к экземпляру объекта то это обращение вынуждено будет подождать окончание конструктора.
Только вот другой поток про это однако ничего знать не будет. и у него метод digest() может выполнится раньше окончания конструктора.

Для того, чтобы этого гарантированно не произошло, надо поставить барьер.
Публикация через volatile создает такой барьер.

Что касается работы с HashMap, то если закрыть все операции с ней одной блокировкой, то все пучком. Но и параллельности никакой.
Запрещать же параллельно читать из map смысла никакого при условии отсутствия модифицирующих операций это безопасно.
Разрешать же параллельно выполнять одну операцию чтения и одну операцию записи ни Вашим и ни нашим. И гарантий никаких и все выстраиваются в очередь.
...
Рейтинг: 0 / 0
больше DCL
    #39392689
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot Сергей Арсеньев]questionerОни имеют право записать в переменную cache адрес отведенного под HashMap участка памяти и пойти выполнять код дальше, а конструктор отложить на потом.
Однако, если встретится обращение к экземпляру объекта то это обращение вынуждено будет подождать окончание конструктора.
Только вот другой поток про это однако ничего знать не будет. и у него метод digest() может выполнится раньше окончания конструктора.



Вот Вы мне объясните как объект может быть расшарен между потоками до того как конструктор его завершился?
...
Рейтинг: 0 / 0
больше DCL
    #39392700
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Повторяю. Out of order execution. Сслыка (адрес участка памяти отведенного под объект) будет известна до вызова конструктора. Поскольку конструктор ее не меняет, то для OoOE пофигу в какой последовательности их выполнять. Ровно до чтения содержимого памяти по этому адресу. Но сам адрес записать в переменную по другому адресу можно.
Если дальше нет барьера - то другой поток может прочесть этот адрес.

Правда для достижения этого нужно добиться этой оптимизации, при этом устроить гонку и заполучить кешлайн в который попал недоинициализированный объект в кеш другого процессора на котором будет исполняться код другого потока (чтоб он и не думал читать актуальное состояние объекта). Да и еще если процы будут TSO архитектуры, они будут этому сопротивляться.
...
Рейтинг: 0 / 0
больше DCL
    #39392710
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,

Повторяю. Out of order execution. Сслыка (адрес участка памяти отведенного под объект) будет известна до вызова конструктора. Поскольку конструктор ее не меняет, то для OoOE пофигу в какой последовательности их выполнять. Ровно до чтения содержимого памяти по этому адресу. Но сам адрес записать в переменную по другому адресу можно.
Если дальше нет барьера - то другой поток может прочесть этот адрес.

Правда для достижения этого нужно добиться этой оптимизации, при этом устроить гонку и заполучить кешлайн в который попал недоинициализированный объект в кеш другого процессора на котором будет исполняться код другого потока (чтоб он и не думал читать актуальное состояние объекта). Да и еще если процы будут TSO архитектуры, они будут этому сопротивляться.

адрес памяти, отведенный под объект этот будет известен кому? Как он и его сможет использовать?

напишите пример кода, пожалуйста.
...
Рейтинг: 0 / 0
больше DCL
    #39392724
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
К тому же в примере с dcl там поле статическое и его могут увидеть, это очевидно, а в нашем случае поле нестатическое
...
Рейтинг: 0 / 0
больше DCL
    #39392829
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerадрес памяти, отведенный под объект этот будет известен кому?
Кому вы захотите присвоить адрес созданного instance Вашего класса Digest, тому и будет виден.
Если он останется только в рамках одного потока, то весь разговор яйца выеденного не стоит.

Еще раз поясняю. Если этот адрес будет ссылаться на участок памяти, который будет в кеше другого процессора взятом тем ядром на момент до окончания работы конструктора и вы не попросите его инвалидировать по окончании работы конструктора, то он останется в виде как есть. То же работает и с JIT компилятором.
...
Рейтинг: 0 / 0
больше DCL
    #39392830
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerК тому же в примере с dcl там поле статическое и его могут увидеть, это очевидно, а в нашем случае поле нестатическое
А сам объект? Как его будут публиковать - гарантии есть?
...
Рейтинг: 0 / 0
больше DCL
    #39392901
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньев,

Я понял кажется вас. Такая ситуация возможна только если мы теряем ссылку из конструктора?

или ещё возможны варианты?
...
Рейтинг: 0 / 0
больше DCL
    #39392915
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Не обязательно из конструктора. Конструктор сам по себе барьера не создает.

грубо говоря
THREAD A
Код: java
1.
2.
3.
static Object myDigester;
....
myDigester= new Digestr() {...};


THREAD B
Код: java
1.
2.
3.
[SRC java]static Object myDigester;
....
if (myDigester!=null) myDigester.digest(...)


уже может создать эту ситуацию.
Код: java
1.
static volatile Object myDigester;


нет
...
Рейтинг: 0 / 0
больше DCL
    #39392995
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньевquestioner,

Не обязательно из конструктора. Конструктор сам по себе барьера не создает.

грубо говоря
THREAD A
Код: java
1.
2.
3.
static Object myDigester;
....
myDigester= new Digestr() {...};


THREAD B
Код: java
1.
2.
3.
[SRC java]static Object myDigester;
....
if (myDigester!=null) myDigester.digest(...)


уже может создать эту ситуацию.
Код: java
1.
static volatile Object myDigester;


нет

опять у Вас static
...
Рейтинг: 0 / 0
больше DCL
    #39393156
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

Не суть, хоть синглетон какой. Вы как в другой тред хотите передать свой экземпляр - через стек?
...
Рейтинг: 0 / 0
52 сообщений из 52, показаны все 3 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / больше DCL
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]