Да, я был некорректен сказав «кэши».
Имел в виду, что в результате пеупорядочения и/или оптимизации кода компилятором/JIT/CPU может возникнуть эффект, будто у вас осталась «ваша копия», а у другого потока «другая копия». Некорректно указывать ГДЕ она «лежит». Спецификации Lang/JMM этого не говорят.
Осторожно, разумная гипотеза!: и, видимо, между загруженным классом (тем же самым загрузчиком, но в другом потоке) и первым использованием загруженного класса устанавливается happens-before отношение. Один раз. При первом использовании.
В Java специфицирован процесс загрузки класса. И в нем четко определена последовательность действий, включая инициализацию статических полей и запуск статических инициализаторов.
Каждый класс, загруженный в JVM определяется ПАРОЙ — {«имя-класса»:String, «загрузчик»:java.lang.ClassLoader}.
ClassLoader можно получить у любого класса средствами самого языка/платформы.
Либо:
ClassLoader loader = MyClass.class;
Либо:
MyClass instance =…
ClassLoader loader = instance.getClass(); // Метод определен в предке всех ссылочных типов — java.lang.Object
.
Когда классу classA требуется classB, то загрузчик класса класса classA автоматически грузит класс classB. При этом происходит «линковка» кода, строковые имена используемых классов превращаются в внутренние структуры JVM представляющие в том числе код методов.
.
При следующем использовании classB из classA — нет необходимости в вызове процедур ClassLoader (содержащих код синхронизации и, как следствие, «дорогих»), так как во внутреннем представлении класса classA используются не «строковые ссылки» (подлежащие разрешению загрузчиком класса, а ссылки на внутренние структуры JMV (представления класса classB)).
Означаетли это что статические поля инициализируются до старта main функции?
В Java такой занятный специфицированный мностадийный процесс ленивой загрузки классов. Я давал ссылку по которой можно высчитать когда произойдет.
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
Вот из-за выделенной строчки загрузка и произойдет «по требованию». Как следует из остальной части спецификации — в момент первого обращения к полю. В ходе выполнения main().
Демонстрация:
class Something {
private Something() {
throw new Error();
}
public static Something getInstance() {
return LazySomethingHolder.something;
}
private static class LazySomethingHolder {
public static Something something = new Something();
}
}
class Test {
public static void main(String[] args) {
System.err.println("Hello!");
System.err.println(Something.getInstance());
}
}
>> Hello!
>> Exception in thread "main" java.lang.Error
>> ...
Кажется, в C++ семантика другая.
Это указание компилятору на то, что переменная подвержена частому изменению и рекомендуется к размещению в регистрах процессора.
Т.е. ваш флаг вообще не будет разделяться ядрами. У каждого — своя копия.
Дело не в До или ПОСЛЕ.
В целях возможности вручную управлять механизмами синхронизации (довольно дорогостоящими) ПО УМОЛЧАНИЮ при отсутствии каких-либо синхронизационных действий — передача данных между кэшами процессоров НЕ ПРЕДПОЛАГАЕТСЯ.
Т.е. у каждого процессора в локальном кэше содержится своя собственная копия флага. И то, что он в одном потоке уже false, не противоречит тому, что в другом в это же время true.
import java.util.List;
public class App {
public <A extends Comparable<B> & List<? super Integer>, B extends Comparable<A>> void func(A a, B b) {
a.add(a.compareTo(b) + b.compareTo(a));
}
}
большинство начинающих не могут без детального объяснения преподавателя сказать — будет это компилироваться или нет?
Да, скажу сразу, мы пережили процедуру «ребрендинга» (переименовались с KharkovITCourses на GolovachCourses), так что канал на youtube у нас все еще со старым названием: youtube.com/user/KharkovITCourses.
В Java нет такого. Статические бывают — только поля (не локальные переменные).
Тут отличие от С++.
Меня оправдывает предусмотрительно вставленное
:)
Имел в виду, что в результате пеупорядочения и/или оптимизации кода компилятором/JIT/CPU может возникнуть эффект, будто у вас осталась «ваша копия», а у другого потока «другая копия». Некорректно указывать ГДЕ она «лежит». Спецификации Lang/JMM этого не говорят.
Пропустил.
Исправлю.
Каждый класс, загруженный в JVM определяется ПАРОЙ — {«имя-класса»:String, «загрузчик»:java.lang.ClassLoader}.
ClassLoader можно получить у любого класса средствами самого языка/платформы.
Либо:
ClassLoader loader = MyClass.class;
Либо:
MyClass instance =…
ClassLoader loader = instance.getClass(); // Метод определен в предке всех ссылочных типов — java.lang.Object
.
Когда классу classA требуется classB, то загрузчик класса класса classA автоматически грузит класс classB. При этом происходит «линковка» кода, строковые имена используемых классов превращаются в внутренние структуры JVM представляющие в том числе код методов.
.
При следующем использовании classB из classA — нет необходимости в вызове процедур ClassLoader (содержащих код синхронизации и, как следствие, «дорогих»), так как во внутреннем представлении класса classA используются не «строковые ссылки» (подлежащие разрешению загрузчиком класса, а ссылки на внутренние структуры JMV (представления класса classB)).
В Java такой занятный специфицированный мностадийный процесс ленивой загрузки классов. Я давал ссылку по которой можно высчитать когда произойдет.
Вот из-за выделенной строчки загрузка и произойдет «по требованию». Как следует из остальной части спецификации — в момент первого обращения к полю. В ходе выполнения main().
Демонстрация:
Если интересно — найду.
Это указание компилятору на то, что переменная подвержена частому изменению и рекомендуется к размещению в регистрах процессора.
Т.е. ваш флаг вообще не будет разделяться ядрами. У каждого — своя копия.
В целях возможности вручную управлять механизмами синхронизации (довольно дорогостоящими) ПО УМОЛЧАНИЮ при отсутствии каких-либо синхронизационных действий — передача данных между кэшами процессоров НЕ ПРЕДПОЛАГАЕТСЯ.
Т.е. у каждого процессора в локальном кэше содержится своя собственная копия флага. И то, что он в одном потоке уже false, не противоречит тому, что в другом в это же время true.
Спасибо за ссылку, действительно классно.
большинство начинающих не могут без детального объяснения преподавателя сказать — будет это компилироваться или нет?
1.материалы к каждой лекции, пример для лекции 2.1
2. Тестовая система на 3.000 вопросов
3. Более 50 лабораторных
youtube.com/user/KharkovITCourses.