将 AtomicLong 递减一定增量的正确方法
Correct way to decrement an AtomicLong by a certain delta
给定一个 AtomicLong
对象,将值递减 delta 的正确方法是什么?
选项 1
AtomicLong count = new AtomicLong(0L);
public void decrementCount(long decrementBy) {
count.getAndUpdate(l->count.get() - decrementBy);
}
选项 2
AtomicLong count = new AtomicLong(0L);
public void decrementCount(long decrementBy) {
count.getAndAdd(-decrementBy);
}
虽然两者都给出了期望的结果,但我想了解在什么情况下它们不会代表期望的行为,即自动递减 long 值? (例如,第二种方法的一个缺点可能是负号导致一些位溢出,但我不确定这是不是真的)
你的第二种方法是正确的,如getAndAdd
):
Atomically adds the given value to the current value
AtomicLong count = new AtomicLong(0L);
count.getAndAdd(-decrementBy);
您的第一种方法略有偏差,因为它在 "The function should be side-effect-free" 时使用 count.get()
和 LongUnaryOperator
,即理想情况下仅使用作为参数给出的长值。虽然读取原子值可能不能严格算作副作用,但没有必要也不必要地使更新成为非原子的。
count.getAndUpdate(l->count.get() - decrementBy);
这不是自动运行的。 getAndUpdate
大致是这样工作的:
long getAndUpdate(LongUnaryOperator op) {
long current;
long newValue;
do {
current = this.get();
newValue = op.apply(current);
while (!compareAndSet(current, newValue));
return current;
}
通过重新读取 lambda 内部的 count.get()
,您正在读取 AtomicLong
then 的值,这可能与值不同current
表示已通过,如果其他线程更新了中间的 AtomicLong
;然后您将根据更新后的值进行更新,而不是 current
.
使用您在 l
中传递的值:
count.getAndUpdate(l->l - decrementBy);
但是 getAndAdd(-decrementBy)
更容易。
我认为这个 class 的所有方法都准备好了:
The AtomicLong class provides you with a long variable which can be
read and written atomically, and which also contains advanced atomic
operations
取决于您希望在更新之前和之后使用的顺序,或者先更新然后阅读。你有递增和递减的 arpopiate 方法:
addAndGet()
getAndAdd()
getAndIncrement()
incrementAndGet()
getAndDecrement()
decrementAndGet()
然后是这样的:
AtomicLong atomicLong = new AtomicLong(22);
System.out.println(atomicLong.getAndAdd(-1));
System.out.println(atomicLong.addAndGet(-1));
给定一个 AtomicLong
对象,将值递减 delta 的正确方法是什么?
选项 1
AtomicLong count = new AtomicLong(0L);
public void decrementCount(long decrementBy) {
count.getAndUpdate(l->count.get() - decrementBy);
}
选项 2
AtomicLong count = new AtomicLong(0L);
public void decrementCount(long decrementBy) {
count.getAndAdd(-decrementBy);
}
虽然两者都给出了期望的结果,但我想了解在什么情况下它们不会代表期望的行为,即自动递减 long 值? (例如,第二种方法的一个缺点可能是负号导致一些位溢出,但我不确定这是不是真的)
你的第二种方法是正确的,如getAndAdd
):
Atomically adds the given value to the current value
AtomicLong count = new AtomicLong(0L);
count.getAndAdd(-decrementBy);
您的第一种方法略有偏差,因为它在 "The function should be side-effect-free" 时使用 count.get()
和 LongUnaryOperator
,即理想情况下仅使用作为参数给出的长值。虽然读取原子值可能不能严格算作副作用,但没有必要也不必要地使更新成为非原子的。
count.getAndUpdate(l->count.get() - decrementBy);
这不是自动运行的。 getAndUpdate
大致是这样工作的:
long getAndUpdate(LongUnaryOperator op) {
long current;
long newValue;
do {
current = this.get();
newValue = op.apply(current);
while (!compareAndSet(current, newValue));
return current;
}
通过重新读取 lambda 内部的 count.get()
,您正在读取 AtomicLong
then 的值,这可能与值不同current
表示已通过,如果其他线程更新了中间的 AtomicLong
;然后您将根据更新后的值进行更新,而不是 current
.
使用您在 l
中传递的值:
count.getAndUpdate(l->l - decrementBy);
但是 getAndAdd(-decrementBy)
更容易。
我认为这个 class 的所有方法都准备好了:
The AtomicLong class provides you with a long variable which can be read and written atomically, and which also contains advanced atomic operations
取决于您希望在更新之前和之后使用的顺序,或者先更新然后阅读。你有递增和递减的 arpopiate 方法:
addAndGet()
getAndAdd()
getAndIncrement()
incrementAndGet()
getAndDecrement()
decrementAndGet()
然后是这样的:
AtomicLong atomicLong = new AtomicLong(22);
System.out.println(atomicLong.getAndAdd(-1));
System.out.println(atomicLong.addAndGet(-1));