У меня просто проблема относительно параллелизма, логический поток которого, когда клиент (называемый Oracle Forms) отправляет запрос (называемый параллельной программой) и вызывает процедуру plsql, эта процедура в конечном итоге вызовет статический метод java.
Я нахожу, что когда я отправляю два запроса в одно и то же время или в очень короткий промежуток времени (например, 1 секунду), некоторые проблемы параллелизма будут замечены.
Метод java является отправной точкой для выполнения того, что поиск из базы данных подсказывает, какие записи следует вставлять в базу данных.
Проблема в том, что они приведут к дублированному результату, поскольку, когда я запрашиваю, оба запроса найдут все возможное, чтобы вставить новые записи.
Я попытался добавить synchronized
в статическом java-методе, но это не решает эту проблему, почему?
Что я делаю:
public static synchronized void execute
Обратите внимание, что вставка будет вызываться в plsql, что означает, что я выполняю недостаточную синхронизацию, если только синхронизирую метод java. Но когда я заглядываю в журнал, он показывает два прогона запроса за ту же секунду, что я не думаю, что это нормально! поскольку база запросов и выполнение этого предложения занимает много времени.
Чтобы сделать Java-метод действительно трудоемким, я добавляю кодовый вызов Thread.sleep(5000)
и регистрирую время после этого кода и регистрирую идентификатор потока.
Сюрприз, чтобы увидеть, что Thread
идентификатор 1! А также время, когда они проходят сон в одно и то же время. Почему это?
Что я могу сделать для решения проблемы? Любая блокировка java-метода или pl sql?
PS: Теперь я пытаюсь использовать DMBS_LOCK
и, похоже, работает, но я все еще надеюсь узнать причину, по которой метод java не синхронизирован.
Я понятия не имею, как реализована JVM внутри БД Oracle, но поскольку (по крайней мере, в некоторых общих конфигурациях) каждое соединение с базой данных получает свой собственный серверный процесс, то, если в каждую из них встроена отдельная JVM, Т ты много хорошего. Вам нужно будет использовать блокировки базы данных.
Предполагая, что вызовы статического метода Java выполняются внутри одного и того же загрузчика классов, synchronized
- это все, что вам нужно.
Возможно, ваш журнал неисправен. Как именно вы регистрируетесь?
Ваше утверждение о том, что поиск базы данных "занимает много времени", не является убедительным. Базы данных, как правило, кэшируют данные, например.
В двух словах: если по вашему определению "атомарная операция" представляет собой комбинацию lookup + insert, вам следует "синхронизировать" по обоим. Приобретение блокировки базы данных выглядит разумным способом.
Thread#sleep
не гарантирует, что текущий поток будет спать X миллисекунд, возможно, контроллер потока (в данном случае, ваша Oracle RBDMS) может отправить сигнал прерывания и разбудить поток, чтобы избежать этой наивной задержки.