powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Нужен ли final в корректно синхронизированных программах?
17 сообщений из 17, страница 1 из 1
Нужен ли final в корректно синхронизированных программах?
    #38549518
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предположим, что мы написали data race free программу. То есть все куски кода их разных потоков общаются друг с другом исключительно через synchronized-with, и всегда видят актуальные значения.
Вопрос такой: существует ли data race free программа, которая не сможет корректно работать без модификатора final? Ну то есть взяли, например, и выпилили final из Java 8. Пострадает ли от этого хоть одна data race free программа?

P.S.: Вопрос касается final исключительно в контексте concurreny. Другие плюшки вроде complie-time проверок и inner классов оставим за скобками.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549611
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну по-моему довольно очевидно, что любую синхронизацию, можно обернуть synchronized(lock), так что вопрос изначально немного лишен смысла. Вы видели в какой-либо книге классической по concurrency понятие final? А вот вопрос удобства и полезности - тут можно дискутировать, да. Основная фишка final в гарантированной безопасной публикации, сделал одну ссылку final и весь граф объектов гарантировано безопасно опубликован. Как-то так считаю
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549638
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник ,
Я не говорил про synchronized , я говорил про synchronized-with , это разные вещи. То есть у нас есть корректно синхронизированная программа, без гонок. Она работает. Теперь мы берем, и выпиливаем все final. Будет ли она работать и дальше?
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549695
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Простите, Вы про warning "Synchronization on non-final field", который вывешивает IDE?

Так это не более чем совет, наряду стем, что строку лучше не использовать как монитор.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549768
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев ,
Нет, я не про это. Я про использование final в корректно синхронизированном коде.
Моя идея очень проста - с точки зрения многопоточности, final нужен только в некорректно синхронизированном коде, то есть в коде, где есть data race.

Приведу пример. Есть программка с некорректной публикацией:
Код: 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.
public class UnsafePublication {

    private static Holder holder;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            public void run() {
                while (holder == null) {
                    // Busy wait.
                }

                assert holder.val != null;
            }
        }).start();

        Thread.sleep(100);

        holder = new Holder();
    }

    private static class Holder {
        private Object val;

        private Holder() {
            this.val = new Object();
        }
    }
}

Здесь объект holder опубликован небезопасно, поэтому другой поток может увидеть holder.val == null, и ассершн упадет. Окей. тогда мы говорим, а давайте ка мы добавим Holder.val модификатор final, и тогда ассершн никогда не упадет. Ну окей, коллеги, добавьте final, и попробуйте запустить этот код. Программа нормально отработала? То то и оно :-)

Мы добавили final, но программа все равно не работает. Не работает она по причине наличия data race на переменной holder, и читатель не может увидеть ее изменение. Программа некорректна. Окей, я могу это легко исправить, сделав holder volatile:
Код: 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.
public class UnsafePublication {

    private static volatile Holder holder;

    public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {
            public void run() {
                while (holder == null) {
                    // Busy wait.
                }

                assert holder.val != null;
            }
        }).start();

        Thread.sleep(100);

        holder = new Holder();
    }

    private static class Holder {
        private final Object val;

        private Holder() {
            this.val = new Object();
        }
    }
}

Окей, holder волатильный, Holder.val финальный. Программа корректно синхронизирвана, в ней нет data race'ов. А теперь вопрос: а нахрена нам теперь нужен final у Holder.val? Он теперь не нужен. Я могу его безопасно удалить, и ассершн никогда не упадет по той причине, что теперь безопасная публикация (действительно безопасная) осуществляется через volatile.

Таким образом, я делаю вывод, что final нужен только в тех случаях, если у нас уже был какой-то косяк в коде, и мы хотим немного его подшлифовать. Если же у нас код корректен, то final не нужен никогда. Пример такого сознательного "косяка" - double checked locking, когда мы сознательно оставляем в коде data race, но при подозрении на его возникновение всегда можем грамотно разрулить ситуацию через тот же final, например.

P.S.: Повторюсь, я говорю про final сейчас исключительно в контексте многопоточности .

P.S
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549900
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Надо посмтреть спецификацию jvm и сравнить все, что касается многопоточности волатилов и финалов. Если волатил ганатирует все что финал или больше, то да, в контексте многопоточности финал не нужен.

но навскидку, финал дает меньше гарантий, в часности если есть

final MyObj x;
MyObj z;

z=new MyObj(10);
x=new MyObj(15);

То другой поток может не увидеть z= MyObj(10), но увидеть x=MyObj(15) а так же увидеть все x.*
А если х будет волатил, то видимость z=MyObj(10) гарантируется.

Поэтому, навкидку (и в контексте многопоточности), финал можно безопасно заменить волатилом, а волатилы финалом - нет.
Но мое мнение не окончательное.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549902
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvА теперь вопрос: а нахрена нам теперь нужен final у Holder.val?

Поскольку Вы сделали holder volatile, то согласно JMM начиная с 1.5 есть ,есть барьер на операции с памятью, который вроде бы гарантирует окончание конструктора до присвоения, а соответственно до чтения (либо null либо отработавший конструктор).

Присвоение final полям значений меняет порядок их назначения. См. http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2
Если внимательно присмотреться к шагам, то можно увидеть когда именно захватывается-отпускается блокировка (а значит появляется барьер последовательности выполнения).
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549903
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokЕсли волатил ганатирует все что финал или больше, то да, в контексте многопоточности финал не нужен.
С одной стороны больше...
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549932
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokА если х будет волатил, то видимость z=MyObj(10) гарантируется.Это не так. Давайте посмотрим на такой вот код:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public class MyObject {
    private int x;
    private volatile int y;

    public MyObject() {
        x = 1;
        y = 2;
    }
}

obj = new MyObject()

Давайте рассмотрим, как отработает последняя строчка в идеальных условиях, когда у нас нет out-of-order execution:

ref = allocate(MyObject);
ref.x = 1;
ref.y = 2; // За volatile store идет "барьер сверху".
_________
---------
obj = ref;

"Барьер сверху" означает, что присвоение x не может убежать за присвоение y. Однако, следующий вариант также является абсолютно валидным с точки зрения JMM:

ref = allocate(MyObject);
ref.x = 1;
obj = ref;
ref.y = 2;
_________
---------

Таким образом мы увидим объект до того, как была инициализирована его волатильная переменная. Так что volatile и final нельзя сравнивать в таком ключе.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38549955
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевПоскольку Вы сделали holder volatile, то согласно JMM начиная с 1.5 есть ,есть барьер на операции с памятью, который вроде бы гарантирует окончание конструктора до присвоения, а соответственно до чтения (либо null либо отработавший конструктор).Нет такой гарантии в JMM. Шипилев недавно поднимал эту тему в concurrency-interest, предлагая сделать такую гарантию для volatile, но ее зарубили - http://cs.oswego.edu/pipermail/concurrency-interest/2013-November/011951.html
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550056
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvТаким образом мы увидим объект до того, как была инициализирована его волатильная переменная. Так что volatile и final нельзя сравнивать в таком ключе.
Вообще говоря и final гарантирует это не всегда. Только если конструктор не публикует свое this.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550071
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvНет такой гарантии в JMM.
Вы путаете волатильное поле создаваемого объекта с волатильной переменной, которой присваивают создаваемый объект.

На Вашем примере - если бы val был волатильным, а холдер нет - была бы гонка.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550075
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хотя я тоже тут плаваю - поэтому написал вроде бы.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550080
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевВообще говоря и final гарантирует это не всегда. Только если конструктор не публикует свое this.Если разработчик объявил поле final, а потом отдал this из конструктора до его инициализации, то это проблема разработчика, а не final.
final дает четкие гарантии при его корректном использовании. Я с таким же успехом могу вам сказать, что synchronized не всегда гарантирует критическую секцию, если использовать разные мониторы.

Еще раз - я говорю про корректно синхронизированную программу, где все инструменты использованы корректно. И я пришел к выводу, что в таких программах final не нужен. У кого есть другие мысли по этому поводу?
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550091
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев Вы путаете волатильное поле создаваемого объекта с волатильной переменной, которой присваивают создаваемый объект.Да, я не правильно вас понял. Ваше утверждение верно.
Мой поинт как раз в этом и заключается, что если гонок нет, то для final просто напросто нет применений. А если гонка все таки есть, то final никогда не избавит нас от нее, но лишь даст немного более предсказуемые результаты.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550138
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvА если гонка все таки есть, то final никогда не избавит нас от нее, но лишь даст немного более предсказуемые результаты.
Ну почему же, большинство народу сходится во мнении, что публикование через Holder (static final) не менее правильно чем dcl с volatile. Да и проще.

Просто любую задачу можно решать по разному.
...
Рейтинг: 0 / 0
Нужен ли final в корректно синхронизированных программах?
    #38550200
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public class MyObject {
    private int x;
    private volatile int y;

    public MyObject() {
        x = 1;
        y = 2;
    }
}

obj = new MyObject()


...
ref = allocate(MyObject);
ref.x = 1;
obj = ref;
ref.y = 2;

Таким образом мы увидим объект до того, как была инициализирована его волатильная переменная.

Так вы ж привели изначально не data race free код, что противоречит условию задачи топикстартера! Поэтому ваш пример не равен моему, и потому он ничего не опровергает.

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


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