代码之家  ›  专栏  ›  技术社区  ›  Molten Ice

对AtomicReference持有的对象执行equals和hashcode的正确方法

  •  2
  • Molten Ice  · 技术社区  · 7 年前

    AtomicReference 不适用于 Objects.equals() Objects.hash() .

        AtomicReference<String> ref1 = new AtomicReference<>("hi");
        AtomicReference<String> ref2 = new AtomicReference<>("hi");
        System.out.println(Objects.equals(ref1, ref2)); //false
        System.out.println(Objects.equals(ref1.get(), ref2.get())); //true but potentially not thread safe
        System.out.println(Objects.hash(ref1) == Objects.hash(ref2)); //false
        System.out.println(Objects.hash(ref1.get()) == Objects.hash(ref2.get())); //true but potentially not thread safe
    

    原子参考 是相等的,并且以一种既能工作又能保证线程安全的方式计算相同的哈希值?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Solomon Slow    7 年前

    检查两个[变量]…是否相等的最佳方法是什么?在某种程度上,这两个变量都可以工作并且是线程安全的?

    你想知道变量是否相等吗?好吧,那又怎样?如果您的“线程安全”相等测试表明它们相等,那么是什么阻止线程B在您执行相等测试的时间和您对信息执行操作的时间之间更改它们中的任何一个。

    当程序处于某个特定状态时 ,然后你想做点什么

    所以,是的,你需要 synchronized

        2
  •  1
  •   Stephen C    6 年前

    首先,我要对以下声明表示异议:

    AtomicReference 不适用于 Objects.equals() 和 Objects.hash()

    事实上, 原子参考 (AR)至少在两种意义上起作用:

    1. AR符合隐含规范。这个 javadocs 表明 equals 和 hashCode 方法不被重写,因此方法的语义由 Object . 因此,AR对象具有 ;也就是说,如果且仅当两个AR对象是同一对象时,它们才是“相等的”。

    2. AR的行为与标准类库定义的其他可变类型一致:数组, StringBuilder Atomic* 类型等等。

    我承认AR的行为可能对你的行为没有帮助。但你会发现 Objects.equals() 对象。哈希() 与我提到的其他可变类型有相同的问题。


      Objects.equals(ref1.get(), ref2.get());
    

    您(正确地)声明这不是线程安全的,但(在我看来)这是原子类型所期望的。一般来说,两个原子操作的序列是非原子的。一般来说,要作为一个原子整体执行两个操作,需要执行某种形式的锁定。

      synchronized (ar1) {
          synchronized (ar2) {
               result = ar1.get() == ar2.get();
          }
      }
    

    缺点是存在死锁的风险。。。如果两个线程同时执行上述代码 ar1 和 ar2 互换。

    对该缺陷的(假设)修复方法是确保线程锁定 和 同样的顺序。你可以(几乎总是)通过使用 ar1.hashCode() 和 ar2.hashCode() 给你一个一致的命令;例如。

      int h1 = ar1.hashCode();
      int h2 = ar2.hashCode();
      if (h1 < h2) {
          synchronized (ar1) {
              synchronized (ar2) {
                   result = ar1.get() == ar2.get();
          }
      } else if (h1 > h2) {
          synchronized (ar2) {
              synchronized (ar1) {
                   result = ar1.get() == ar2.get();
          }
      } else if (ar1 == ar2) {
          result = true;
      } else {
          // h1 == h2, but ar1 != ar2
      }
    

    但正如你所见,在很小的一部分情况下,hashCode排序是行不通的。

    是 解决这个问题的办法。。。使用互斥锁。


    原子参考 对象确实引用了同一个对象,该结果仅在特定时间内有效。测试完成后的瞬间,结果可能会被某个线程更改其中一个ARs而失效。

    底线是测试是 没用

    这个 另一种方法是使用外部锁定 Lock 或者互斥对象不存在潜在死锁问题。

        3
  •  0
  •   Meini    7 年前

    equals 从而使 线程安全。

    我想你不能就这样 AtomicReference