Подскажите, как делают refresh_token взрослые дяди в многопоточке.
Если нужен ответ на это конкретный вопрос, причем если имеется в виду не просто многопоточка, а асинхронная, с await без блокировки потока - то на это есть такой SemaphoreSlim. Делается примерно так (надеюсь, идея будет понятна)
//Попадаем сюда после получения существующего access token и выявления, что он просрочен
SemaphoreSlim sem = GetSemaphore(clientId);
await sem.WaitAsync(); //timeot и CancellationToken добавить по вкусу
try {
//Получаем существующий access token повторно - вдруг его уже кто-нибудь до нас обновил
// (используем double check pattern)
//Если это не так, выполняем тут всю логику обновления access token
}
finally {
sem.Release(); //SemaphoreSlim - не мьютекс, сам не освободится в случае чего
}
GetSemaphore реализовать можно по-разному. Можно один на все приложение: static или Singleton - это если нагрузка небольшая.
А можно кэшировать семафоры по одному для каждого пользователя (т.е. свой семафор для каждого clientID), чтобы пользователи не толклись около одного семафора на всех.
Главное, чтобы этот семафор создавался с начальным значением 1 - тогда он будет пускать пользователей по одному.
Ну, а если все делать без асинхронности, в одном потоке, блокируя его при необходимости (т.е. без await), то способов много. Простейший - блок lock вокруг кода обновления маркера доступа (access token), есть такде Monitor, Mutex, тот же Semaphore (хоть со Slim, хоть без)...