背景
我的系统使用访问令牌来访问平台 API。
我有一个线程 A 每 2 分钟更新一次访问令牌。
然后处理前端请求的其他线程将使用访问令牌进行 API 调用。
提供访问令牌的平台本身已经实现了一些令牌重叠机制。也就是说,在生成新令牌后的 30 秒内,旧令牌仍然可用。
想法
我有一个如下所示的界面:
public interface AccessTokenService {
String fetchAccessToken();
void refreshAccessToken();
}
显然,处理它的最简单且无错误的方法是使这两种方法同步。但是,由于代币提供平台内置了代币重叠。我认为不需要“同步”来使其业务正常。另外,由于我的系统高度依赖API调用,使方法同步会导致性能下降。
问题
我的问题是,在底层,JVM 如何处理多线程字符串写入/读取。
比如说,一个字符串 accessToken 正在从“abc”更改为“def”。同时,一些线程正在尝试读取 accessToken 的值。读取的可能输出是什么?
由于 java 中的字符串是不可变的,因此您的阅读线程只能获取旧令牌或新令牌,而不能将某些东西混合在一起。
对引用的更新总是原子的(这里也是:您的阅读线程可以读取旧引用或新引用,但不能混合在一起)。
只有一点需要注意:存储当前令牌的字段必须声明为volatile
,否则读取线程可能会缓存它们看到的某些值。
您的 AccessTokenService 的虚拟实现可能如下所示:
public class DummyAccessTokenService implements AccessTokenService {
private volatile String currentToken = null;
@Override
public String fetchAccessToken() {
return currentToken;
}
private int tokenNumber = 0;
@Override
public void refreshAccessToken() {
currentToken = String.format("Token-%d", tokenNumber++);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句