我的服务中有一个缓存作为成员变量,我正在创建一个方法,通过jmx mbean公开它,这样我就可以在运行时拆除并重新创建具有新缓存过期时间的vogon缓存:
public class CachedVogonService implements CachedVogonServiceMBean {
private LoadingCache<String, Vogon> cache;
private long expiryInSeconds;
private VogonService service;
public CachedVogonService(VogonService newService,
long newExpiryInSeconds) {
this.expiryInSeconds = newExpiryInSeconds;
this.service = newService;
this.cache = createCache(newService, newExpiryInSeconds);
}
private LoadingCache<String, Vogon> createCache(
VogonService newService,
long expiryInSeconds) {
return CacheBuilder.newBuilder()
.refreshAfterWrite(expiryInSeconds, TimeUnit.SECONDS)
.build(new VogonCacheLoader(
Executors.newCachedThreadPool(), newService));
}
/**
* This is the method I am exposing in JMX
*/
@Override
public void setExpiryInSeconds(long newExpiryInSeconds) {
this.expiryInSeconds = newExpiryInSeconds;
synchronized (this.cache) {
this.cache = createCache(service, expiryInSeconds);
}
}
我担心我的锁定技术会导致jvm保留对旧缓存的引用,并防止它被垃圾收集。
如果我的服务对象丢失了对synchronized块中旧缓存的引用,那么当执行退出该块时,它是否仍会将旧缓存对象标记为已锁定-使其无法用于垃圾收集?
1条答案
按热度按时间h9vpoimq1#
通过查看为类似情况生成的字节码,我们可以看到锁定字段的对象地址是重复的,用于获取和释放锁。所以原始锁定对象用于锁定。
在同步块中使用新对象更改锁定字段后,另一个线程可以获取新对象的锁,并可以进入同步代码块。像这样使用synchronized不会在线程之间提供同步。您应该使用另一个对象进行锁定(例如final object cachelock=new object())
仅出于信息目的,这种用法并不能阻止垃圾回收。因为这里提到的对象地址在这个方法的堆栈帧内,一旦这个方法完成执行,堆栈帧就会被销毁,对旧对象的引用也就不存在了(但不要像这样使用synchronized。)
您可以在这里检查jvm指令集