gpt4 book ai didi

java - 访问两个 AtomicIntegers 作为一个操作线程安全吗?

转载 作者:搜寻专家 更新时间:2023-11-01 03:16:00 25 4
gpt4 key购买 nike

在 Brian Goetz 的 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.

我从这一段中了解到,如果我们将 setUppersetLower 函数同步,那么也会有一些情况当对象可能达到无效状态时。但是,我认为如果两个函数都是同步的,那么只有一个线程可以执行其中一个函数,并且每个函数都有必要的不变量检查。我们如何才能处于无效状态。任何人都可以举例说明。我在这里缺少什么?

如果我理解正确,那么这一行的意义是什么:

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.

最佳答案

摘自“Java 并发实践”一书:

NumberRange could be made thread-safe by using locking to maintain its invariants, such as guarding lower and upper with a common lock. It must also avoid publishing lower and upper to prevent clients from subverting its invariants.

这意味着下面的代码是线程安全的:

@ThreadSafe
public class NumberRange {

@GuardedBy("this") private int lower, upper;

public synchronized void setLower(int i) {
if (i > upper) {
throw new IllegalArgumentException("can't set lower to " + i + " > upper");
}
lower = i;
}

public synchronized void setUpper(int i) {
if (i < lower) {
throw new IllegalArgumentException("can't set upper to " + i + " < lower");
}
upper = i;
}

public synchronized boolean isInRange(int i) {
return (i >= lower && i <= upper);
}
}

在这种情况下,NumberRange 提供了自己的锁定以确保复合操作是原子的。

关于java - 访问两个 AtomicIntegers 作为一个操作线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52376830/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com