Надежный способ разблокировать заблокированный блок синхронизации - PullRequest
0 голосов
/ 07 апреля 2020

Иногда система генерирует СЕРЬЕЗНУЮ ошибку в синхронизированном блоке, и возникает попытка перехвата, которая теоретически должна инициировать процесс разблокировки потока, однако это не инициируется. Поэтому я могу сделать вывод, что это не рассматривается как исключение в системе. Есть ли разумный способ обработки указанной блокировки?

Рассмотрим следующий код из board.jsp:

account = Account.get(accountID);
Object synch=account;

if(synch == null) {
    %>No account.<%
    return;
}
try {
    synchronized(synch) {
        ....
    }
} catch (Exception e) {
    ....
} finally {
    ....
}

пример дампа

SEVERE: Scheduled tasks not running!
Apr 07, 2020 4:59:36 PM ExecLauncher:execLauncher run
SEVERE: ---------------------
Thread is: "http-bio-8080-exec-18" Id=122 BLOCKED on com.main.Account@5a0b8133 owned by "http-bio-8080-exec-7" Id=38
        at org.apache.jsp.realtime.board_jsp._jspService(board_jsp.java:192)
        -  blocked on com.main.Account@5a0b8133
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)

Спасибо за внимание :)

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

Это не исключение, а, скорее, говорит, что поток "http-bio-8080-exe c -18" не может быть выполнен, поскольку он пытается войти в синхронизированный (синхронизированный) блок. Он не может войти в этот блок, потому что монитор в настоящее время удерживается потоком "http-bio-8080-exe c -7".

Поэтому первым делом нужно выяснить, почему "http-bio- 8080-exe c -7 "не отпускает монитор. Это может быть просто проблема с производительностью, поскольку многие потоки пытаются выполнить tissecition параллельно. Или нить может быть висит. Вы можете проанализировать это, сгенерировав дамп потока:

Чтобы сгенерировать дамп потока go в папку bin вашей установки java. Существует инструмент под названием jps (jps.exe на windows). Выполните его, вы увидите номер (pid) и название программы. Найдите свою программу и выполните jstack [pid]. jstack также находится в папке bin вашей Java установки.

Затем вы увидите, что каждый поток делает в вашей программе, и что поток, которым в данный момент принадлежит монитор, делает.

Существует способ подождать только определенное время c, чтобы попытаться получить блокировку. Я не совсем уверен, решит ли это вашу проблему, но для полноты вот так. Используйте блокировку повторного входа вместе с tryLock:

 if( lock.tryLock(long timeout,
          TimeUnit unit))
 { try {
   // ... method body
 } 
 finally {
   lock.unlock()
 } 
 }
 else {
    // lock could not be acquired at the given time
 }
0 голосов
/ 08 апреля 2020

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

account = Account.get(accountID);
Object synch=account;
Lock lock = new ReentrantLock();


if(synch == null) {
    %>No account.<%
    return;
}
try {
lock.lock();
    /* Your actual code which you were executing in 
      the synchronized block */
} catch (Exception e) {
    ....
} finally {
    lock.unlock(); // this will work
}
...