java将两个原子整数作为一个线程安全的操作来访问?
在Brian Goetz的《实践中的Java并发》(Java Concurrency In Practice)中,有一个例子如下:
public class NumberRange {
// INVARIANT: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i) {
// Warning -- unsafe check-then-act
if (i > upper.get())
throw new IllegalArgumentException(
"can't set lower to " + i + " > upper");
lower.set(i);
}
public void setUpper(int i) {
// Warning -- unsafe check-then-act
if (i < lower.get())
throw new IllegalArgumentException(
"can't set upper to " + i + " < lower");
upper.set(i);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
}
我知道上面的代码容易出现竞争情况
然后他解释如下:
Multivariable invariants like this one create atomicity requirements: related variables must be fetched or updated in a single atomic operation. You cannot update one, release and reacquire the lock, and then update the others, since this could involve leaving the object in an invalid state when the lock was released.
我从这一段中了解到,如果我们使setUpper
和setLower
函数synchronized
,那么也会出现对象可能达到无效状态的情况。然而,我认为如果两个函数都是同步的,那么只有一个线程可以执行其中一个函数,并且每个函数都有必要的不变量检查。我们怎么能处于无效状态。任何人都可以举个例子来演示。我错过了什么
如果我理解正确,那么这句话的意义是什么:
You cannot update one, release and reacquire the lock, and then update the others, since this could involve leaving the object in an invalid state when the lock was released.
# 1 楼答案
从《Java并发实践》一书中:
这意味着以下代码是线程安全的:
在这种情况下,
NumberRange
提供了自己的锁定,以确保复合动作是原子的