Нет, этот код не является потокобезопасным. Поскольку блокировка происходит внутри операторов if, два потока могут создать токен примерно в одно и то же время. Учтите следующее:
- Тема 1 входит
else
блок
- Тема 1 уступает теме 2
- поток 2 входит
else
блок
- Поток 2 блокирует
syncRoot
, создает новый токен (токен A) и назначает его на TOKEN
- Поток 2 возвращает "токен A".
- Поток 2 уступает потоку 1
- Поток 1 блокирует
syncRoot
, создает новый токен (токен B) и назначает его TOKEN
- Поток 1 возвращает "токен B".
Ваша система теперь использует два разных токена, которые были созданы только на расстоянии нескольких секунд, и Thread
ссылается на "токен B".
Edit:
Вы можете сделать свой поток безопасным, взяв блокировку еще до проверки токена. Приведенный ниже пример блокирует каждый вызов Get()
, поэтому он не будет создавать два токена одновременно (почти) одновременно с вашим кодом. Вы также можете использовать другие схемы блокировки, некоторые из которых могут повысить производительность.
public static string Get()
{
lock(syncRoot)
{
if (string.IsNullOrEmpty(TOKEN) || !TokenIsValid())
TOKEN = CreateNewToken();
return TOKEN;
}
}