Java RMI и синхронизированные методы - PullRequest
16 голосов
/ 18 августа 2010

Я изучаю книгу «Распределенные системы» (Tanenbaum & Van Steen), и они говорят что-то, что кажется противоречащим тому, что многие думают о Java RMI и синхронизированных методах.

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

Я видел, что многие люди придерживаются такого же мнения, посмотрите здесь, например: Вопросы по Java RMI и Thread Synchronization

В книге вместо этого сказано, что одновременное выполнение синхронизированных методов не предотвращается при использовании RMI.

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

Логически, блокировка в удаленном объекте это просто. Предположим, что клиент А звонит синхронизированный метод удаленного объект. Сделать доступ к удаленному объекты выглядят всегда одинаково Что касается локальных объектов, это было бы необходимо заблокировать А в заглушка на стороне клиента, которая реализует интерфейс объекта и к которому А имеет прямой доступ. Аналогично, другой клиент на другой машине будет нужно также заблокировать локально прежде чем его запрос может быть отправлен сервер. Следствием является то, что мы нужно синхронизировать разных клиентов на разных машинах. Как мы обсуждали в гл. 6, распределен синхронизация может быть довольно сложной.

Альтернативным подходом было бы разрешить блокировку только на сервере. В в принципе, работает нормально, но проблемы возникают при сбое клиента в то время как его вызов обрабатывается на сервере. Как мы обсуждали в Глава. 8, мы можем потребовать относительно сложные протоколы, чтобы справиться с этим ситуация, и что это может существенно повлиять на общее выполнение удаленного метода вызовы.

Поэтому разработчики Java RMI решили ограничить блокировку на удаленные объекты только для прокси (Wollrath et al., 1996). Это означает что потоки в том же процессе будут быть лишенным одновременно доступ к тому же удаленному объекту, но нити в разных процессах будут нет. Очевидно, что эти синхронизации семантика хитрая: в синтаксической уровень (т. е. при чтении исходного кода) мы можем увидеть хороший, чистый дизайн. Только когда распределенное приложение фактически выполнено, неожиданно можно наблюдать поведение, которое должно были рассмотрены во время разработки. [...]

Я думаю, что на статью "Модель распределенных объектов для системы Java" ( доступна здесь ) в тексте упоминается примечание Wollrath et all, 1996 в скобках. Однако единственный соответствующий абзац, который я нашел на этой статье, это:

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

Я неправильно интерпретирую текст или фактически указано, что синхронизированные методы "не так синхронизированы" при использовании RMI?

Ответы [ 4 ]

12 голосов
/ 02 сентября 2010

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

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

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

1 голос
/ 18 августа 2010

Вы также должны знать, что многопоточность Java значительно изменилась с 1996 года. Методы notify () и wait (), которые были частью оригинального языкового дизайна, получили много шума от экспертов по параллелизму и Java 5 (2004 По словам вики) высокоуровневые объекты параллелизма , такие как ReentrantLock , были введены, что теперь является предпочтительным способом ведения дел.

Таким образом, упомянутая вами критика, вероятно, верна, но устарела.

1 голос
/ 18 августа 2010

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

0 голосов
/ 18 июня 2011

Вы правы. Текст неверный. Заглушки RMI поточно-ориентированы и могут вызываться одновременно несколькими потоками в одной клиентской JVM. Мне не известны какие-либо утверждения или тексты Уоллрата и других, в которых говорится что-то другое, и я слежу за этой темой с 1997 года.

В частности:

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

Вы правы.

В книге вместо этого говорится, что одновременное выполнение синхронизированных методов не предотвращается при использовании RMI.

Книга не только ошибочна, но и заявляет о невозможности. Как именно RMI может предотвратить работу синхронизации?

Логически, блокировка удаленного объекта проста. Предположим, что клиент A вызывает синхронизированный метод удаленного объекта.

Затем на сервере происходит обычная работа Java.

Чтобы доступ к удаленным объектам всегда выглядел точно так же, как к локальным объектам, необходимо было бы заблокировать A в заглушке на стороне клиента, которая реализует интерфейс объекта и к которой A имеет прямой доступ.

Мусор. Тот факт, что реализация удаленного метода synchronized делает все необходимое.

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

Опять это мусор.

Следствием этого является необходимость синхронизации разных клиентов на разных машинах.

Снова мусор.

Альтернативный подход - разрешить блокировку только на сервере.

'Разрешить'? Что это значит? synchronized метод synchronized. Вы не можете запретить это.

В принципе, это работает нормально, но проблемы возникают, когда клиент падает, пока его вызов обрабатывается сервером.

Снова мусор. Таких проблем не возникает. Сервер восстанавливается из этой ситуации либо через тайм-аут чтения, либо за исключением записи, либо даже при успешном завершении удаленного метода. Во всех трех случаях метод завершается, блокировка синхронизации снимается, и срок службы продолжается.

Как мы обсуждали в гл. 8, нам может потребоваться относительно сложные протоколы для обработки этой ситуации, которые могут существенно повлиять на общую производительность удаленных вызовов методов.

Ерунда.

Поэтому разработчики Java RMI решили ограничить блокировку удаленных объектов только прокси (Wollrath et al., 1996).

Я не знаю, на что еще это может ссылаться, кроме отрывка, который вы цитировали, и я много раз читал эту статью. Если авторы хотят полагаться на этот документ, они должны были предоставить цитату и надлежащую ссылку на главу и стих.

В любом случае дизайнеры RMI не сделали такого выбора. Не было такого выбора, чтобы сделать. synchronized - это synchronized независимо от того, что разработчики RMI могли или не могли пожелать, и аналогично notify() и wait() * final. Они не могли сделать любой выбор. Предоставленная вами цитата не является «выбором»: это всего лишь утверждение о семантике Java.

Я неправильно интерпретирую текст или фактически указано, что синхронизированные методы "не очень синхронизированы" при использовании RMI?

Я думаю, что вы читаете это правильно, и это совершенно и совершенно неправильно, и не только неправильно, но очевидно неправильно. Как это может быть правильно?Java RMI не и, действительно, не может никоим образом не изменяет, не удаляет и не расширяет семантику synchronized.

...