Тупик на ReentrantLock в перехватчике

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

Это мой код в Interceptor:

private val lock = ReentrantLock()
...
private fun tryRefreshToken(chain: Interceptor.Chain): Boolean {

        if (lock.tryLock()) { // refresh token by single thread
            try {
                tryRefreshToken(chain, credentialsProvider)
            } catch (e: TokenRefreshFailedException) {
                return false
            } finally {
                lock.unlock()
                }
            return true
        } else {
            // another threads should wait here for token refresh
            lock.lock() // here I catch deadlock
            return true
        }
    }

Если этот метод возвращает true — токен обновляется, false — если обновление токена не удалось.

Как исправить мой тупик и где моя ошибка?


person Artem    schedule 24.09.2018    source источник
comment
Вы можете использовать метод synchronized или блок   -  person Ravindra Kushwaha    schedule 24.09.2018
comment
@RavindraKushwaha покажи свой вариант?   -  person Artem    schedule 24.09.2018
comment
Пожалуйста, обратитесь к этому stackoverflow.com/a/31656463/3946958   -  person Ravindra Kushwaha    schedule 24.09.2018
comment
почему вы не используете lock.lock() в первую очередь?   -  person user6327816    schedule 24.09.2018
comment
@RavindraKushwaha, пожалуйста, прочитайте мой пост еще раз!   -  person Artem    schedule 24.09.2018
comment
@RahulKumar, потому что я хочу обновить токен только первым потоком, а другие потоки должны его ждать   -  person Artem    schedule 24.09.2018
comment
как насчет указания блокировки в месте, где вы проверяете, нужно ли обновлять токен? Таким образом, если вы хотите обновить токен, токен будет обновлен, и все ожидающие потоки получат кешированный токен после его обновления.   -  person user6327816    schedule 24.09.2018


Ответы (2)


Чтобы выполнить ваше требование, вы должны создать Producer-Consumer токена... Вы должны использовать блокировку/ожидание и уведомление, поэтому первый поток будет обновлять токен, а другой поток будет ждать, пока поток обновления не уведомит их... пример приложения по этой ссылке на Oracle.

person Anis BEN NSIR    schedule 24.09.2018

Я отлаживаю и читаю журналы, и я нахожу решение своей проблемы:

else {
        // another threads should wait here for token refresh
        lock.lock() // here I wait for token refresh
        lock.unlock() // here I free monitor
        return true
    }
person Artem    schedule 24.09.2018