在上一篇文章中,我们讨论了异步查询到同步以优化服务器性能。在本文中,我们将讨论双重检查锁定的设计模式。通过预先简单地检查锁状态,该模式减少了锁获取次数,通常提高了性能。
以下是之前关于锁和线程安全的一些文章:
首先,让我们看一个简单的严格同步示例:虽然这个类是线程安全的,但是我们可以看到仍然有一个明显的性能缺陷:每次我们想要获得单个实例的实例时,我们都需要获得可能不需要的锁。为了解决这个问题,我们可以首先验证是否需要先创建对象,只有在这种情况下,我们才能获取锁。
此外,我们希望在进入同步块后立即再次执行相同的检查,以保持原子操作:
使用此模式时要记住的一点是,字段必须是可变的,以防止缓存不一致。事实上,JA内存模型只允许发布部分初始化的对象,这反过来又会导致其他错误。尽管双重检查锁定可能会加快速度,但至少有问题。基于这些原因,让我们看看没有这些缺陷的其他解决方案。以下所有方法都将同步任务交给JVM。
此外,正如我们在上一段Java语言规范参考中所知,类初始化是在我们每次使用它的方法或字段时发生的,我们可以使用嵌套的静态类来实现延迟初始化:
在这种情况下,instanceholder类将在我们每次通过调用getInstance访问字段时被分配。
解决方案使用枚举而不是类。在撰写本文时,这被认为是编写单个示例的最简单、最安全的方法:
总之,本文介绍了双重检查的锁定方式、局限性和一些可供选择的方法。在实践中,过多的冗余和缺乏向后兼容性使得这种模式容易出错,因此我们应该避免这种情况。相反,我们应该考虑使用另一种方法来同步JVM。