为什么在实践书中将并发的SafePoint类标记为@ThreadSafe?

gst*_*low 4 java concurrency multithreading thread-safety

在《 Java并发实践》一书中,您可以找到以下代码:

@ThreadSafe
public class SafePoint { 
    @GuardedBy("this") private int x, y;
    private SafePoint(int[] a) { this(a[0], a[1]); }
    public SafePoint(SafePoint p) { this(p.get()); }
    public SafePoint(int x, int y) { 
        this.x = x;
        this.y = y;
    }
    public synchronized int[] get() { return new int[] { x, y };
    }
    public synchronized void set(int x, int y) { this.x = x;
        this.y = y;
    }
}
Run Code Online (Sandbox Code Playgroud)

此标记为 @ThreadSafe

我很确定此类不是线程安全的(如果我正确理解了这个术语的话)。

例:

 SafePoint racePublishedSafePoint; // field

 // thread 1:
 racePublishedSafePoint = new SafePoint(1,1);

 // thread 2:
 SafePoint sp;
 while(true){
   SafePoint sp = racePublishedSafePoint;
   if(sp != null) break;
 }
 System.out.println(sp.get()[0]);
 System.out.println(sp.get()[1]);
Run Code Online (Sandbox Code Playgroud)

我相信有几种可能的结果:

  1. 应用程序没有完成
    其他
  2. 如果申请完成,我们可以看到
    a)0 0
    b)0 1
    c)1 0
    d)1 1

我对吗?

如果为true,那么为什么作者将类标记为线程安全?我认为线程安全类-无需复杂分析即可用于并发应用程序的类。

作者想说什么?

聚苯乙烯

我已阅读 Private构造函数以避免出现竞争情况

...而且我的话题不是重复的。

Ale*_*lev 6

我同意操作规范,认为该示例似乎违反了对@ThreadSafe担保的通常理解。不安全的发布竞赛是非常真实的,当然,SafePoint通过竞赛发布时,您会看到令人费解的行为。一些现实生活中的线程安全类在恶意出版物中幸免于难(这String是一个臭名昭著的例子),加重了混乱。

就JCIP的叙述而言,我没有纸质或电子副本,因此请Doug Lea(主要作者之一)联系,他说:

我认为混乱的部分在JCIP文本中。我认为不@ThreadSafe涉及出版物竞赛,也不 涉及在构建期间可能遇到的任何其他竞赛。出版物安全性单独处理。

不过,我可以看到人们会怎么想。这是我们探索始终在构造函数中放置发布围栏的原因之一。

Doug谈论的最后一部分在“所有领域都是最终的”中作了简要描述,包括动机,实验补丁和性能估计。