首页 文章

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

提问于
浏览
2

在Java Concurrency in Practice一书中,您可以找到以下代码:

@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;
    }
}

这标记为 @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]);

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

  • 应用程序未完成
    其他

  • 如果申请完成,我们可以看到
    a)0 0
    b)0 1
    c)1 0
    d)1 1

我对吗?

如果为true,为什么作者将该类标记为线程安全?我认为这个线程安全的类 - 可以在没有复杂分析的情况下用于并发应用程序 .

作者想说什么?

P.S.

我看过Private constructor to avoid race condition

......我的主题不重复 .

1 回答

  • 2

    我同意OP的观点,这个例子似乎违反了通常对 @ThreadSafe 保证的理解 . 不安全的出版比赛是非常真实的,当然,你可以通过比赛发布 SafePoint 时看到令人费解的行为 . 一些现实生活中的线程安全类可以在有趣的出版物中存活( String 是一个臭名昭着的例子),这加剧了混乱 .

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

    我认为混淆的部分在JCIP文本中 . 我不认为@ThreadSafe涵盖出版比赛,或在施工期间可能遇到的任何其他比赛 . 出版物安全性单独处理 . 不过,我可以看到别人怎么想 . 这是我们探索始终在构造函数中放置释放栅栏的原因之一 .

    Doug正在讨论的最后一部分在_1429698中进行了简要描述,包括动机,实验补丁和性能估计 .

相关问题