скалогрыз писал(а):Итог: билдер патерн, нужен только в Яве, в паскале он не нужен! Ура! Ява программисты, пишите больше и толще!
Гг.
Модератор: Модераторы
скалогрыз писал(а):Итог: билдер патерн, нужен только в Яве, в паскале он не нужен! Ура! Ява программисты, пишите больше и толще!
скалогрыз писал(а):я не говорил про струтурное программирование, я говорил про "отсутствие подпрограмм" специально-же цитату посдставляю!
...и выражаю своё сомнение в твоей уверенности, относительно того как и что оптимизирует процессов.
скалогрыз писал(а):Очереднёсть инструкций гарантируется в паскале для конкретного потока.
Это значит, что создав объект, я точно уверен, что все пременные в нём как надо, и я могу спокойно его раздавать в другие потоки
скалогрыз писал(а):По твоим утверждениями, такой гарантии (даже для одно потока) в Яве нет. ...но на самом деле есть, но это неважно.
Mirage писал(а):Все эти оптимизации и перемещения инструкций как компилятором, так и процессором производятся так, что не могут быть обнаружены в рамках одного потока.
скалогрыз писал(а):Тебе нужен явный контроль видимости данных. Я полагаю, сейчас в твоих проектах все данные доступны всем (потокам) всегда и контроль ведётся только за счёт иммутабельности.
скалогрыз писал(а):Радости мало, зато очень точно и эффективно можно контроллировать что, куда и когда попадёт.
Контроль = Надёжность.
Mirage писал(а):А не надо мнений. Если полагаешь, что процессоры оптимизируют код, учитывая специальным образом команды call, ret и т.п., то покажи место в спецификации конкретного процессора, где такое написано.
Mirage писал(а):Ага, т.е. ты уверен, что если на момент получения ссылки на сконструированный объект, все команды по его инициализации находятся выше по тексту программы, то его можно передавать другим потокам?
Mirage писал(а):И действительно, если в этом же потоке проверить все поля, то будут получены правильные значения!
Но, тем не менее, другой поток может увидеть не правильные.
Причем, что совсем не очевидно, даже если оставить проверки в первом потоке.
Mirage писал(а):Иммутабельность очевидно не отменяет ни инкапсуляцию, ни другие принципы. Просто позволяет избежать необходимости синхронизации там, где она не нужна. Единственная проблема - неопределенность момента (с т.з. других потоков), когда все данные иммутабельного объекта инициализированы до своих значений. И эта проблема решается гарантиями конструктора таких объектов.
У тебя в примере эта проблема тоже решается (хотя ты тут её существование отрицаешь) явными и довольно тяжелыми синхронизациями.
Mirage писал(а):Точнее всего контролировать позволит написание на ассемблере, т.к. примитивы синхронизации у каждого процессора свои.
Да и как ты без ассемблера или volatile проконтролируешь, что переменная пишется именно в память, а не, скажем, в регистр?
скалогрыз писал(а):Гугл в помощь! никакого желания нет курить мануалы процессоров
скалогрыз писал(а):повторюсь - да.
скалогрыз писал(а):только если ты передал ссылку на объект второму потоку, до конца инициализации
(даже ява-устав тебе об этом говорит).
Устав Java писал(а):The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, 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.
скалогрыз писал(а):я отрицаю "эту проблему" в твоей формулировке.
Потому что ты утверждаешь, что другой поток может получить доступ к не инициализированному объекту, без твоего ведома.
И потому, ты требуешь сделать инициализацию атомарной и втиснутой в единый конструктор.
скалогрыз писал(а):Я же утверждаю, что другой поток, НЕ сможет получить доступ к объекту, пока я ему сам не передам этот объект.
А это значит, что я не ограничен в том, как я буду инициализировать объект.
скалогрыз писал(а):Вопрос регистр, не регистр - остаётся компилятору, и рассматривается компилятором. А т.к. такого понятия как "volatile" в паскале нет, то и компилятору с этим вопросом проще.
скалогрыз писал(а):"Тяжёлые" синхронизации гарантируются на уровне операционной системы-> заботится о конкретном процессоре не приходится -> в программе нет никаких ассемблерных вставок -> кроссплатформенный код.
скалогрыз писал(а):* всё что может быть использовано разными потоками, должно позаботится о синхронизации, используя "тяжёлые" объекты синхронизации (а других-то средств синхронизации нет)
Mirage писал(а):Зачем тогда пытаться использовать как аргумент то, о чем понятия не имеешь?
Mirage писал(а):А другой поток его сам взять может?
Mirage писал(а):Ты, видать, подзабыл. Напомню:Устав Java писал(а):The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, 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.
Т.е. это про только final-поля.
Обычные поля таким свойством не обладают и могут иметь дефолтные значения после конструктора, даже если они явным образом инициализировались в нем. Почему - из-за вышеобсужденных эффектов оптимизаций компилятора и процессора. Т.е. это отнюдь не магия явы. Чтобы этого не было, на современном железе нужно принимать специальные меры.
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
Mirage писал(а):скалогрыз писал(а):я отрицаю "эту проблему" в твоей формулировке.
Потому что ты утверждаешь, что другой поток может получить доступ к не инициализированному объекту, без твоего ведома.
И потому, ты требуешь сделать инициализацию атомарной и втиснутой в единый конструктор.
Это фантазия очередная, я такого не утверждал. И уж совсем ничего не требовал.
Mirage писал(а): Единственная проблема - неопределенность момента (с т.з. других потоков), когда все данные иммутабельного объекта инициализированы до своих значений. И эта проблема решается гарантиями конструктора таких объектов.
Mirage писал(а):И действительно, если в этом же потоке проверить все поля, то будут получены правильные значения!
Но, тем не менее, другой поток может увидеть не правильные.
Mirage писал(а):За атомарность как раз ты утверждал, даже без конструктора.
Mirage писал(а):Т.е. если ты передашь ссылку другому потоку "как положено", т.е. с синхронизацией, то наплевать на гарантии конструктора (а также функции-инициализатора вместе со структурным программированием тоже)?
Mirage писал(а):Компилятору-то проще "рассмотреть вопрос" о использовании регистра, а вот программисту, если ему надо на это повлиять, ох как не просто.
Mirage писал(а):Ну т.е. везде вставляем тяжелые синхронизации и радуемся жизни. И тормозам.
Я же за наличие возможностей легкой синхронизации - volatile, атомарные операции, CAS'ы и т.п.
Причем включенных в платформу (в случае FPC - в компилятор и RTL) так, чтобы все это было удобно в использовании и при этом предсказуемо работало.
Mirage писал(а):Да ладно? А мужики-то не знают...
FormatFloat(MaxFloatLength, Max);
FormatFloat(Max, MaxFloatLength);
FormatFloat.MaxLength(MaxFloatLength).Value(Max).F
hinst писал(а):так что же там первым идёт, длина строки или само число
hinst писал(а):MaxFloatLength у меня длина строки, а Max это само число
скалогрыз писал(а):точно знаю, что out-of-order execution на итоговый результат не влияют.
т.е. выражение ( 2 + 2 ) * 2 всегда будет давать результат 8, а не 6.
И не важно, что в процессоре закешировано (2+2) или ??? * 2
Соответственно с инструкциями "ret" тоже самое.
скалогрыз писал(а):это как так "взять"?
скалогрыз писал(а):и снова возвращаемся к примеру из устава
...
вот что я утверждаю (прошу согласится или нет с каждым утверждением)
1. public FinalFieldExample() - это конструктор
2. y = 4 присваивается в теле конструктора
3. int j = f.y; // could see 0 - ситуация "see 0" может возникнуть только в том, случае если конструктор не завершён.
4. f = new FinalFieldExample(); - вызов конструктора присваивает ссылку на объект раньше, чем конструктор завершён (иначе случая в пункте 3 не могло бы быть)
5. исходя из пункта 4, я могу судить, что данный код - это пример некорректного использования final полей, т.к. сказано: " do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished."
скалогрыз писал(а):хм... может быть я тебя на правильно понял:
1) требование внести инициализацию в конструктор, т.к. только он может что-либо гарантировать.Mirage писал(а): Единственная проблема - неопределенность момента (с т.з. других потоков), когда все данные иммутабельного объекта инициализированы до своих значений. И эта проблема решается гарантиями конструктора таких объектов.
скалогрыз писал(а):2) утверждение про потоки (состояние "гонок"):Mirage писал(а):И действительно, если в этом же потоке проверить все поля, то будут получены правильные значения!
Но, тем не менее, другой поток может увидеть не правильные.
скалогрыз писал(а):Атомарность для одного потока. Требование на то, чтобы ссылка на объект передавалась другим потокам по завершению инизициализации (конструктора, функции, функций, методов... и какого угодно кода) остаётся.
скалогрыз писал(а):В принципе, я могу без проблем передать указатель на объект в поток. (естественно после инициализации объекта).
Это ничему не повредит, и работать приложение будет как ожидается.
скалогрыз писал(а):Но в последствии я получу другую проблему - в какой момент времени можно объект освободить.
Это не проблема, если поток работающий с объектом один - он может и может освободить объект.
А вот если потоков несколько? или объект должен быть использован после того как поток проделал с ним работу. В итоге, я упираюсь в необходимость иметь явную синхронизацию.
скалогрыз писал(а):А тебе не надо на него влиять (...пока asm функции не начнёшь писать).
Больше того, тебе вредно на него влиять. Ещё хуже, ты НЕ можешь на него повлиять никак. Даже если опишешь все переменные как "register" или "volatile" или ещё как-нибудь.
Переменных много, а регистров набор строго ограничен (живописен и разнообразен на разных процессорах), все не поместятся, и что-то перейдёт в память.
скалогрыз писал(а):аха вот это "везде вставляем тяжёлые синхронизации" как раз первый неверный шаг.
Вставлять нужно не "везде", а там где надо. В интересах самого программиста, чтобы таких "надо" мест, было как можно меньше. (меньше синхронизации - больше скорость, меньше ошибок)
скалогрыз писал(а):Кстати - про тормоза - пожалуйста с тестами и сравнением производительности.
Mirage писал(а):скалогрыз писал(а):...
вот что я утверждаю (прошу согласится или нет с каждым утверждением)
3. int j = f.y; // could see 0 - ситуация "see 0" может возникнуть только в том, случае если конструктор не завершён.
4. f = new FinalFieldExample(); - вызов конструктора присваивает ссылку на объект раньше, чем конструктор завершён (иначе случая в пункте 3 не могло бы быть)
5. исходя из пункта 4, я могу судить, что данный код - это пример некорректного использования final полей, т.к. сказано: " do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished."
3. Смотря как определить с т.з. другого потока понятие "конструктор завершен".
С одной стороны, f.y еще не присвоен. Значит, конструктор не завершен.
С другой, переменной f уже даже присвоена ссылка на объект, что даже видно из другого потока, откуда и вызывается reader(). Значит, конструктор завершен.
4. Не, не раньше. Из того же потока как не смотри, не раньше. Если передать раньше, то с final полями тоже беда будет.
5. Не, с final полями-то все как раз хорошо. Та часть конструктора, что инициализирует final поля, гарантированно отработала, в полном соответствии с заявленной моделью памяти.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 32