【问题标题】:How to resolve memory leak in multi threading envionment?如何解决多线程环境中的内存泄漏?
【发布时间】:2019-02-14 06:24:54
【问题描述】:

我在多线程环境中有一个有趣的内存泄漏案例。 我有以下逻辑:

public void update(string key, CustomObj NewResource)
{
  //fetch old resource for the given key from the concurrent hashmap
  // update hashmap with the newResource for the given key
  // close the old resource to prevent memory leak    
}

public void read (string key)
{
   // return resource for the given key
}

现在如果我有两个线程:
Thread#1:调用 update 方法更新 key K 的资源
Thread#2:调用read方法读取同一个key K的资源。

注意:CustomObj 属于第三方库,所以我不能在其中放入 finalize 方法来关闭它。

即使在读取和更新方法上使用同步也无济于事,因为更新线程可以在读取线程仍在使用资源时关闭资源。

您能告诉我在这种情况下如何在不发生内存泄漏的情况下保持线程安全吗?

【问题讨论】:

  • 只要让reader线程在读完资源后负责关闭资源
  • @ErwinBolwidt 我认为这行不通。我们可以让多个阅读器同时进行读取操作。由于资源尚未过时,读者没有必要关闭。

标签: java multithreading memory-leaks


【解决方案1】:

你不应该使用finalize(),原因太宽泛,无法在此讨论。

如果多个线程可以同时处理一个对象,那么您可以使用“引用计数”来跟踪何时应该关闭资源。

当前与对象一起工作的每个线程/函数/等在获得对对象的访问权时都会将其“用户计数”增加一。当它停止使用它时,它会将其“用户数”减一。将计数减为零的线程将关闭该对象。您可以利用 java 标准库提供的各种“原子”原语来创建无锁解决方案。

由于这是来自第三方库的对象,您需要创建某种包装器来跟踪引用。

PS:通常在线程间使用具有共享状态的对象并不是一个好主意 - 它会带来麻烦 - 同步问题、数据竞争、同步中的性能损失等。

【讨论】:

  • 您好,感谢您的回答。如果这个对象是KafkaProducer,你觉得我需要担心吗? Kafka是否会优雅地关闭生产者(等到生产者被其他线程使用)
  • 回避finalize()的最大原因很容易解释:当可用堆空间变低时触发GC。它不会因任何其他原因触发;不是当操作系统用完文件句柄时,不是当它用完套接字时,不是因为你的程序可能需要“清理”的任何其他事情。
猜你喜欢
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2018-04-11
  • 2020-04-07
  • 1970-01-01
相关资源
最近更新 更多