这是一个类:
@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: Concurrency in Practice》中,作者对同一对象上的
value
和两个方法进行了保护。我无法理解这如何有助于解决竞争条件。首先,set()
不是一个复合操作。那么,我们为什么需要对其进行同步?即使这样做,竞争条件也不会消失。一旦线程从 set()
方法退出并释放锁,另一个线程就可以获取锁并设置新值。在初始线程中执行 get()
将返回新值,违反了后置条件。(我知道作者是为了可见性而保护
get()
),但我不确定它如何消除竞争条件。
get()
时都应该得到8!如果你想要每个线程拥有自己的值,你需要使用线程局部变量——请参见ThreadLocal
类。 - user85421m()
,并且该方法所涉及的每个对象都是线程安全的,每个方法都是线程安全的,但这仍然不足以保证方法m()
是线程安全的。 - Solomon Slow