首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >覆盖同步锁中使用的变量会阻止它的垃圾回收吗?

覆盖同步锁中使用的变量会阻止它的垃圾回收吗?
EN

Stack Overflow用户
提问于 2019-02-04 22:12:34
回答 1查看 112关注 0票数 2

我在我的服务中有一个缓存作为成员变量,我正在创建一个方法来通过JMX MBean公开它,这样我就可以在运行时使用新的缓存到期时间拆除并重新创建我的vogon缓存:

代码语言:javascript
运行
复制
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保留对旧缓存的引用,并防止它被垃圾收集。

如果我的服务对象丢失了对同步块内的旧缓存的引用,那么当执行退出该块时,它是否会将旧的缓存对象仍然标记为锁定-使其不可用于垃圾回收?

EN

Stack Overflow用户

回答已采纳

发布于 2019-02-05 05:32:53

通过查看为类似情况生成的字节码,我们可以看到锁定字段的对象地址是重复的,并用于获取和释放锁。所以使用原始的锁定对象来进行锁定。

在synchronized块内用新对象修改锁字段后,另一个线程可以获取新对象的锁,进入synchronized代码块。像这样使用同步,不会提供线程之间的同步。您应该使用另一个对象进行锁定。(如最终对象cacheLock =新对象())

仅供参考,这种用法不会阻止垃圾收集。由于这里提到的对象地址位于此方法的堆栈框架内,一旦该方法完成执行,堆栈帧将被销毁,并且不再保留对旧对象的引用。(但不要像这样使用synchronized。)

您可以检查JVM指令集here

代码语言:javascript
运行
复制
public class SyncTest {

    private Long value;

    public static void main(String[] args) {
        new SyncTest().testLock();
    }

    public SyncTest() {
        value = new Long(1);
    }

    private void testLock() {
        synchronized (this.value) {
            this.value = new Long(15);
        }
    }
}

  private void testLock();
     0  aload_0 [this]
     1  getfield t1.SyncTest.value : java.lang.Long [27] // push value field to operand stack
     4  dup // duplicate value field push it to operand stack
     5  astore_1 // store the top of the operand stack at [1] of local variable array (which is the duplicated value field)
     6  monitorenter // aquire lock on top of the operand stack 
     7  aload_0 [this]
     8  new java.lang.Long [22]
    11  dup
    12  ldc2_w <Long 15> [31]
    15  invokespecial java.lang.Long(long) [24]
    18  putfield t1.SyncTest.value : java.lang.Long [27]
    21  aload_1 // load the [1] of local variable array to the operand stack (which is the duplicated value field previously stored)
    22  monitorexit // release the lock on top of the operand stack
    23  goto 29
    26  aload_1
    27  monitorexit
    .....
票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54518024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档