背景
我的系统使用访问令牌来访问平台API。
我有一个线程A来每2分钟更新一次访问令牌。
然后处理前端请求的其他线程将使用访问令牌进行API调用。
提供访问令牌的平台本身已实现了一些令牌重叠机制。也就是说,在生成新令牌后,旧令牌仍然可用30秒。
思想
我有如下界面:
public interface AccessTokenService {
String fetchAccessToken();
void refreshAccessToken();
}
显然,处理它的最简单且无错误的方法是使这两种方法同步。但是,由于令牌提供平台内置了令牌重叠。我不认为需要“同步”才能使其正常运营。此外,由于我的系统高度依赖于API调用,因此使方法同步会导致性能下降。
问题
我的问题是,JVM如何处理多线程字符串写/读。
比如说,字符串accessToken正在从“abc”更改为“def”。同时,一些线程正试图读取accessToken的值。读取的可能输出是什么?
答案 0 :(得分:1)
由于java中的字符串是不可变的,因此读取线程只能获取旧令牌或新令牌,但不能混合在一起。
引用的更新总是atomar(在这里:你的阅读线程可以读取旧引用或新引用,但不能混合在一起)。
只有一点要注意:存储当前令牌的字段必须声明为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++);
}
}