poo*_*oja 2 java garbage-collection phantom-reference finalize finalizer
我正在使用 Mysql GET_LOCK在分布式系统中实现锁定服务。在调用我的 getLock() 方法时,如果客户端获得了锁,我会在数据库中创建一个条目并在释放锁时删除该条目。
假设调用客户端将在达到其目的后释放锁。但是,我想确保在客户端不释放它或不进行适当清理的情况下释放锁。
一种方法是在我的锁定对象上使用 finalize 方法以在调用 finalize 时释放它。然而,它并不理想,增加了复杂性并且在 Java 9 中被弃用。我读到了比终结器更好的 Phantom 引用,但它的复杂程度也很高。我把它作为我的最后手段。
有没有更简单、更少依赖 JVM 的方法来处理这个用例?
不要这样做。问题大于好处。
无论您使用的是终结、参考 API 还是 a Cleaner(基于参考 API),尝试使用对象的生命周期来控制锁会产生更多问题。
不能保证对象会被垃圾回收。只要有足够的空闲堆内存,JVM 就没有理由让垃圾收集器运行。此外,即使垃圾收集器运行时,也不能保证它会收集所有不可达的对象。像 G1GC 这样的垃圾收集器专注于在给定的时间限制内回收尽可能多的内存,优先考虑对象年龄的影响。事实上,他们甚至不知道一个死物在周围躺了多久。
因此,当 JVM 对 GC 收集一堆较新的对象感到满意时,某个特定的无法访问的对象可能会在无限时间内保持未收集状态。
更糟糕的是,对象有可能比预期更早地收集垃圾。对于显式锁定和解锁操作,这没有影响,因为程序的行为保持不变。但是,当您将对象的生命周期与解锁操作联系起来时,您就遇到了麻烦。这尤其适用于当对象只服务于锁定和解锁动作而解锁动作已被应用程序员遗忘时,换句话说,在执行锁定动作后,锁定对象完全未被使用。
为了防止早期收集,您需要类似的东西Reference.reachabilityFence(lockObject),但是当程序员忘记执行所需的解锁操作时,他们记住插入必要的可达性栅栏的可能性有多大?他们更容易插入所需的解锁操作。
任何解决这个问题的尝试都远非简单,同时仍然不能提供值得付出努力的保证。你最好强烈提醒你的锁类的用户需要解锁它。考虑AutoCloseable在try-with-resource块中实现和宣传使用它。
| 归档时间: |
|
| 查看次数: |
167 次 |
| 最近记录: |