Делает ли использование только неизменяемых типов данных потоком программы Java безопасным? - PullRequest
0 голосов
/ 22 сентября 2010

Правда ли, что если я использую только неизменный тип данных, моя Java-программа будет поточно-ориентированной?

Какие-либо другие факторы будут влиять на безопасность потока?

**** Буду признателен, если можете привести пример. Спасибо!** **

Ответы [ 6 ]

7 голосов
/ 22 сентября 2010

Безопасность потоков - это защита общих данных, а неизменяемые объекты защищены только для чтения. Кроме того, когда вы их создаете, но создание объекта является потокобезопасным.

Стоит сказать, что разработка большого приложения, использующего ТОЛЬКО неизменяемые объекты для обеспечения безопасности потоков, будет затруднена.

Это сложный предмет, и я бы порекомендовал вам прочитать Параллелизм Java на практике это очень хорошее место для начала.

3 голосов
/ 22 сентября 2010

Это правда.Проблема в том, что на ваше приложение накладывается довольно серьезное ограничение - использовать только неизменяемые типы данных.У вас не может быть постоянных объектов с состоянием, которые существуют в потоках.

Я не понимаю, зачем вам это делать, но это не делает его менее правдивым.

Подробности и пример: http://www.javapractices.com/topic/TopicAction.do?Id=29

2 голосов
/ 22 сентября 2010

Если бы каждая переменная была неизменной (никогда не изменялась после назначения), у вас действительно была бы тривиально поточно-ориентированная программа.

Функциональное программирование * Среда 1004 * использует это преимущество.

Тем не менее, довольно сложно сделать чисто функциональное программирование на языке, не предназначенном для него с нуля.

Тривиальным примером того, что вы не можете сделать в чисто функциональной программе, является использование цикла, поскольку вы не можете увеличить счетчик. Вместо этого вы должны использовать рекурсивные функции для достижения того же эффекта.

Если вы просто заблуждаетесь в мире безопасности и параллелизма потоков, я бы искренне рекомендовал книгу Гетца Параллельность Java на практике . Он написан для Java, но на самом деле проблемы, о которых он говорит, актуальны и на других языках, даже если решения этих проблем могут быть другими.

0 голосов
/ 23 августа 2012

Любая программа, в которой нет доступа к изменяемым аспектам состояния программы более чем одним потоком, будет тривиально поточно-ориентированной, так как каждый поток также может быть своей отдельной программой. Однако полезная многопоточность обычно требует взаимодействия между потоками, что подразумевает существование некоторого изменяемого общего состояния.

Ключом к безопасному и эффективному многопоточности является включение изменчивости на правильном «уровне проектирования». В идеале каждый аспект состояния программы должен быть представлен одной неизменяемой (*), изменяемой ссылкой на объект, наблюдаемое состояние которого является неизменным. Только один поток за раз может попытаться изменить состояние, представленное определенной изменяемой ссылкой. Эффективная многопоточность требует, чтобы «изменяемый слой» в состоянии программы был достаточно низким, чтобы разные потоки могли использовать разные его части. Например, если один имеет неизменную структуру данных AllCustomers и два потока одновременно пытаются изменить разных клиентов, каждый из них будет генерировать версию структуры данных AllCustomers, которая включает в себя свои собственные изменения, но не версию другого потока. Не хорошо. Однако, если бы AllCustomers был изменяемым массивом объектов CustomerState, один поток мог бы работать на AllCustomers[4], в то время как другой работал на AllCustomers[9], без помех.

(*) Корневой путь должен существовать, когда аспект состояния становится релевантным, и не должен изменяться, когда доступ актуален. Например, можно создать AddOnlyList<thing>, который содержит thing[][] с именем Arr, который был инициализирован до размера 32. Когда добавляется первое, Arr[0] будет инициализироваться, используя CompareExchange, в массив 16 thing. Следующие 15 вещей будут идти в этом массиве. При добавлении 17-й вещи Arr[1] будет инициализирован с использованием CompareExchange для массива размером 32 (который будет содержать новый элемент и 31 элемент после него). Когда будет добавлена ​​49-я вещь, Arr[2] будет инициализирован для 64 предметов. Обратите внимание, что хотя thing сам по себе и содержащиеся в нем массивы не будут полностью неизменными, только самый первый доступ к любому элементу будет записью, и как только Arr[x][y] будет содержать ссылку на что-либо, он будет продолжать делать это до тех пор, пока как Arr существует.

0 голосов
/ 22 сентября 2010

Несмотря на то, что неизменяемые объекты помогают в обеспечении безопасности потоков, «локальные переменные» и «синхронизация» могут оказаться более практичными для программирования в реальном мире.

0 голосов
/ 22 сентября 2010

Неизменность обеспечивает безопасность от определенных вещей, которые могут пойти не так в многопоточных корпусах. В частности, это означает, что свойства объекта, видимого одному потоку, не могут быть изменены другим потоком, пока этот первый поток использует его (поскольку ничто не может изменить его, тогда, очевидно, другой поток не может).

Конечно, это работает только в том случае, если этот объект идет. Если изменяемая ссылка на объект также является общей, то некоторые случаи межпоточных ошибок могут возникать из-за того, что туда помещается новый объект (но не все), поскольку может не иметь значения, работает ли поток с объектом, который уже был заменен. , но опять же, это может иметь решающее значение).

В общем, неизменность следует рассматривать как один из способов обеспечения безопасности потоков, но не единственный и не обязательно сам по себе.

...