Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ещё раз о volatile 
:(
    Опции темы
Рубильник
Дата 20.9.2018, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 6.6.2016

Репутация: нет
Всего: нет



Есть у нас 2 класса, один ссылается на другой.

Код

public class Master{
    public int i=0;
    public Worker worker = null;
}

public class Worker{
    public int size=0;
    public void setSize(int _size){
        size = _size;
   }
   public int getSize(){
        return size;
   }
}

И есть у нас много потоков, которые видят экземпляр класса Master, и из него дергают метода класса Worker.
Предположим, что мы гарантируем другими средствами, что методы Worker одновременно не вызываются несколькими потоками. Нужно ли ставить volatile на переменную size, или будет достаточно поставить на переменную worker?

Формально переменную size читают и записывают разные потоки, значит как бы надо её делать volatile.
Но тогда нужно получается делать volatile ВСЕ поля ВСЕХ внутренних классов(на которые есть зависимости). У вас есть класс, который хранит "базу данных" (список Городов-Магазинов-Продавцов-Товаров- ....), то придется вешать volatile на все эти классы?
В какой момент переменная заносится в мастер копию потока?

Переменная worker не меняется, и общая для потоков.
Поток один выполнят worker.setSize(5);
затем второй поток через 1 секунду выполняет worker.setSize(10);
Опять первый поток через 2 секунды читает worker.getSize();

Есть ли возможность, что первый поток прочитает 5 из своей мастер копии, а не 10?
Есть ли возможность, что оптимизатор раскроет явно инструкции класс Worker (как inline метод), и это повлияет на работу программы.

PM MAIL   Вверх
Рубильник
Дата 20.9.2018, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 6.6.2016

Репутация: нет
Всего: нет



Уточню свой вопрос.

Код

class A{
   public static Object syn = .... // объект для синхронизации

   public Master master = null; // переменная инициируется в конструкторе, общая для всех экземпляров и не меняет значение
   

   public  int calc(int _k){
        synchronized(syn){
            master.worker.size = _k;
        }
        ... 
        int n = 0;
        synchronized(syn){
            n = master.worker.size;
        }
        return n+_k;

   }
}


Может ли случится так, что оптимизатор, увидев, что между записью и чтением в master.worker.size ничего с этими полями не происходит, решит прочитать не из объекта, а из кеша (или мастер копии)?
PM MAIL   Вверх
LSD
Дата 20.9.2018, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15708
Регистрация: 24.3.2004

Репутация: 209
Всего: 537



Цитата(Рубильник @  20.9.2018,  12:15 Найти цитируемый пост)
Предположим, что мы гарантируем другими средствами, что методы Worker одновременно не вызываются несколькими потоками.

Зависит от того, что это за средства.
Т.е. если это будет synchronized на одном и том же объекте - то тогда ВСЕ изменения (с любыми переменными) которые будут делать внутри этого synchronized блока, будут видны потокам которые потом зайдут в этот synchronized блок.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Рубильник
Дата 20.9.2018, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 6.6.2016

Репутация: нет
Всего: нет



synchronized сбрасывает кеш? Сбрасывает при входе в блок, или при выходе из блока?

"на одном и том же объекте"
Уточните этот момент. Если synchronized идет на разных объектах, тогда как?

"будут видны потокам которые потом зайдут в этот synchronized блок"
А если блоков несколько? 
Код

public synchronized void a(){
   ....
}

public synchronized void b(){
   ....
}

Будут ли изменения сделанные в методе a() одним потоком видны другому потоку в методе b()?

Что же это получается: один и тот же метод, вызванный внутри блока синхронизации и вызванный просто так, будут работать по разному? Один с общей памятью, а второй с мастер-копией. Т.е. методу есть разница где его вызвали?

Это сообщение отредактировал(а) Рубильник - 20.9.2018, 14:13
PM MAIL   Вверх
LSD
Дата 20.9.2018, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15708
Регистрация: 24.3.2004

Репутация: 209
Всего: 537



Цитата(Рубильник @  20.9.2018,  14:40 Найти цитируемый пост)
synchronized сбрасывает кеш? Сбрасывает при входе в блок, или при выходе из блока?

"на одном и том же объекте"
Уточните этот момент. Если synchronized идет на разных объектах, тогда как?

1. Забудь про все эти "сбрасывать кэш", "писать напрямую в память" и прочую ересь.
2. Есть Java Memory Model которая оперирует терминами видимости изменений между разными потоками. Там это описывается посредством Happens Before - если один участок кода находится в отношении Happens Before с другим - то все изменения которые произведены в первом будут видны во втором. Как это будет реализованно - установкой memory barrier , сбросом кэшей или еще как - не оговаривается. (например в случае с одноядерной x86 машиной, JVM вообще ничего не нужно делать)
3. Конкретно про synchronized - говориться что освобождение монитора Happens Before захвата этого же монитора другим тредом. Для разных мониторов такой гарантии - нет.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1220 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.