使POJO线程安全

时间:2018-12-13 19:52:06

标签: java multithreading

这是课程:

@NotThreadSafe
public class MutableInteger {
    private int value;
    public int get() { return value;}
    public void set(int value) { this.value = value;} 
}

这是我想出的后置条件:get()返回的值等于set()设置的值或0。

很容易看出上述后置条件并不总是成立。以两个线程A和B为例。假设A将value设置为5,然后B将其设置为8。在线程A中执行get()会返回8。应该返回5。这是一种简单的竞争情况。

如何使此类线程安全?在 Java:并发性实践一书中,作者保护了value并将这两种方法都放在同一个对象上。我不明白这对比赛条件有什么帮助。首先,set()不是复合动作。那么,为什么我们需要同步它?即使在那之后,竞赛条件也不会消失。一旦线程从set()方法退出,一旦释放了锁,另一个线程就可以获取该锁并设置一个新值。在初始线程中执行get()将返回新值,这违反了后置条件。

(据我了解,作者正在保护get())以获取可见性。但是我不确定它如何消除比赛条件。

1 个答案:

答案 0 :(得分:1)

  

首先,set()不是复合动作。那么,为什么我们需要同步它?

您并不是自己同步set(),而是针对同一个对象同步get()set()方法(假设您使这两个方法都同步了)。 )

如果您没有这样做,并且value变量未标记为易失性,那么您将无法保证线程会看到正确的值,因为-线程缓存。 (线程a可以将其更新为5,然后即使线程b更新了线程a仍可能看到8 这就是缺少在这种情况下线程安全。)

您是正确的,所有引用分配都是原子的,因此在这种情况下不必担心引用损坏。

  

即使在那之后,竞赛条件也不会消失。一旦线程从set()方法退出,一旦释放锁,另一个线程就可以获取该锁并设置新值。

就线程安全而言,设置新值的新线程(或设置新值的新代码)根本不是问题,这是设计和预期的。问题在于结果是否不一致,或者特别是如果多个线程能够以不一致的状态并发查看对象。