缓存的哈希码字段应该具有哪些修饰符?

时间:2015-05-08 22:13:41

标签: java multithreading caching serialization

给定一个不可变对象,有时候缓存其哈希码是有意义的。以下是一个例子。

在这个例子中,我意识到缓存比重新计算hashCode更昂贵。

  public class ImmutableObject{
    final int immutableField1;
    final String immutableField2;

    //volatile? transient? WeakReference?
    private Integer cachedHashCode = null; 

    @Override
    public int hashCode() {
      Integer ret=cachedHashCode;
      if(ret == null) {
        ret = immutableField1;
        ret = 31 * ret + immutableField2.hashCode();
      }
      cachedHashCode = ret;
      return ret;
    }
    // constructor, equals, other methods...

  }

cachedHashCode需要哪些修饰符?

  • 易失性:有效的Java建议在此处使用volatile修饰符(how caching hashcode works in Java as suggested by Joshua Bloch in effective java?)。由于类是不可变的,在什么条件下非严格的执行顺序是危险的?是否仅仅是为了防止hashCode的冗余计算?
  • 瞬态:如果派生哈希码,重新计算它几乎肯定比序列化/反序列化更便宜。您希望在什么条件下序列化哈希码?
  • WeakReference:如果类只有几个字段,但hashCode缓存仍然(某种程度上)值得,缓存的哈希码可能会显着增加每个对象的内存占用量。那么缓存应该是WeakReference吗? WeakReference总是占用至少与缓存的int一样多的空间吗?

1 个答案:

答案 0 :(得分:0)

易失性:

是。这样可以确保在赋值后,将其写入内存,程序的所有其他线程都会看到它。如果没有volatile或synchronized块,则无法保证其他人可以看到写入的值。这种魔法在Java内存模型中定义。

瞬态:

是。但是,仅对标记为可序列化的类有意义。您永远不想序列化易于重新计算的内容。也许只有重新计算需要付出很多努力,才有意义。这是典型的空间/时间权衡决策。

的WeakReference:

没有。这增加了更多的开销。如果要将安全内存更改为int值。添加额外标志或定义一个特殊号码,用于"需要计算"目的