|
|
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
Привет. Есть следующий код: Код: java 1. 2. 3. 4. Thread1 | Thread2 foo.collection = new ArrayList<>(); | foo.collection.size(); Верно ли что Thread2 никогда не получит NPE при обращении к ссылке на коллекцию? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 08:50 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
Нет, так как возможна следующая ситуация: Код: java 1. 2. 3. А возможна и такая: Код: java 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 09:13 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
ngc , Не до конца дочитал ваш пост, но ответ не меняется :-) То, что вы выделили красным, все равно никаких гарантий не дает, NPE возможен, если: 1) Был указанный мною выше out-of-order в конструкторе; 2) Поток 2 сделал чтение до того, как поток 1 сделал запись. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 09:15 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
cdtyjv, Извините, не уточнил. Код: java 1. 2. 3. 4. 5. 6. как в таком случае будет выполнена публикация объекта? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 10:28 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
cdtyjv, к пункту 2 - опять же не уточнил - коллекция не изменяется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 10:30 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
out of order в конструкторе возможен, но присвоение final полю происходит вне конструктора поэтому ситуация: ref = reference(Foo); foo = ref; ref.collection = Collections.emptyList(); невозможна. Кроме того, такая ситуация невозможна, даже если collection не волатильная, т.к. foo - финальное. После инициализации final поля с других потоков гарантировано доступны все поля, которые присваивались до присвоения финал-полю, и в него "вложены". Другое дело, что в криво написаном коде можно умудриться сделать foo.collection.size() до того, как сделается final Foo foo = new Foo(), тогда конечно npe. А так мое ИМХО - npe не должно возникнуть. еще вот тут интересно и почти по теме cheremin.blogspot.com/2011/12/final.html ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 15:16 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
chabapok, Спасибо. Допустим если не final но при этом collection is volatile, что тогда? Из JMM мне пока не очень понятно поведение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 16:03 |
|
||
|
Видимость изменения состояния переменной
|
|||
|---|---|---|---|
|
#18+
Если foo не финал, то его присвоение можно реордерить. Тогда, существует опасность, что у вас из за реордеринга foo уже будет не null, но при этом конструирование foo еще не завершено и строчка volatile Collection<> collection = Collections.emptyList(); еще не выполнилась. И если это произойдет, то тогда даже вот такое в другом потоке: if (foo!=null) foo.collection.size(); потенциально приведет к npe. Кроме того, в особо кривом случае, возможен случай что я написал выше -- само присваивание Foo foo = new Foo() не выполнилось и foo равно null, а вы уже из другого потока хотите получить foo.collection Вот вам еще ссылка www.youtube.com/watch?v=qeCGjVf780s там про правила реордеринга Оcновная идея -- записи в обычные поля не выносятся вперед записей волатилов. Назад выноситься могут. таким образом, чтение из волатилов гарантирует видимость всех действий, которые были до записи в волатил этого значения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.02.2014, 16:40 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=188&tid=2127719]: |
0ms |
get settings: |
8ms |
get forum list: |
10ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
32ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
34ms |
get tp. blocked users: |
1ms |
| others: | 245ms |
| total: | 345ms |

| 0 / 0 |
