gpt4 book ai didi

java AtomicInteger decrementAndGet 未按预期工作

转载 作者:行者123 更新时间:2023-12-01 17:15:48 24 4
gpt4 key购买 nike

AtomicInteger 的 decrementAndGet 在多线程操作中似乎无法正常工作。尽管incrementAndGet工作正常。我从执行器中以 10 个线程运行该程序。每个线程在循环中将该值递减 5 次,因此 10 个线程会将其值减小到 -50。但我没有得到-50 的值。如果我调用incrementAndGet 做同样的事情,它确实会增加到50。

public class RunCountAtomic {

public static AtomicInteger aValue = new AtomicInteger(0);

public void runLoop() {
for(int i=0;i<5;i++) {
// aValue.getAndIncrement();
doSomeWork();
aValue.decrementAndGet();
}
System.out.println(" Expected value is - (5 x 10 thread = -50) , actual is: " +aValue.get());
}
// Some dummy work!
public void doSomeWork() { try {Thread.sleep(100); } catch (InterruptedException e) {} }
}

结果显示incrementAndGet确实工作正常,但decrementAndGet却不能!大家是否也有这样的观察呢?或者我可能在代码中遗漏了一些东西。

下面是调用上述类方法的测试代码:

[根据回复评论更新]更新我的 TestMainRL 代码以使用执行器服务来简化它。

public static void main(String[] args) {
int noOfThreads = 10;
ExecutorService e = Executors.newFixedThreadPool(noOfThreads);

List<Future<Boolean>> fblist = new ArrayList<Future<Boolean>>(noOfThreads);

System.out.println("Starting");
// Run the async task in multiple threads.
for (int i = 0; i<noOfThreads; i++) {
TestMainRL t = new TestMainRL();
fblist.add(t.asyncTask ( e));
}

//Just to wait all thread to complete.
//try {for(Future<Boolean> fb: fblist) {fb.get();}} catch (Exception e1) {e1.printStackTrace();}
e.shutdown();
System.out.println("Completed!");

}

顺便说一句,下面是显示最后一个线程不是-50的结果:

Starting
Completed!
Thread[pool-1-thread-1,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -42
Thread[pool-1-thread-2,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -42
Thread[pool-1-thread-6,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -46
Thread[pool-1-thread-7,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -50
Thread[pool-1-thread-5,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -49
Thread[pool-1-thread-3,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -49
Thread[pool-1-thread-4,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -49
Thread[pool-1-thread-10,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -46
Thread[pool-1-thread-8,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -46
Thread[pool-1-thread-9,5,main] Expected value is - (5 x 10 thread = -50) , actual is: -46

在得到@acm的回复后,我意识到要实现只有一个线程应该打印-50的目标,并且使用下面的代码是可能的,它不使用ReentrantLock和下面的RunCountAtomic代码:

public class RunCountAtomic {
public static AtomicInteger aValue = new AtomicInteger(0);
public void runLoop() {
int x = 0;
for(int i=0;i<5;i++) {
doSomeWork();
x = aValue.decrementAndGet(); // decrement and store it in local x.
}
// Here at the time of this query post, I was printing aValue.get() instead of using stored x,
// which will ensure that only one thread will have -50.
System.out.println(Thread.currentThread()+" Value in thread " +x);
}
public void doSomeWork() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
} // Some dummy work!
}

获得 -50 的线程是最后一个线程,它执行了最后一次减量。但是在执行 system.out 时,它可能不会在最后打印。

最佳答案

你到底期待什么?所有线程都返回 -50,最后一个线程返回 -50?您提供的代码中并不能保证这一点。

AtomicInteger 的行为符合预期。您确实可以保证至少有一个线程将返回 -50,这确实发生了,对吧?

关键点是System.out.println -> PrintStream#println:

public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}

所以你的所有线程都在调用这个,但这种类型的锁不公平。因此,即使最后一个到达此锁的线程是值为 -50 的线程,它也可能不是第一个被打印的线程,因此您可以保证 -50 > 被打印,但在某些时候不是最后一次。

要测试解释,您可以使用公平性为 true 的 ReentrantLock,这意味着最早的等待线程将首先被唤醒。更改 RunCountAtomic 如下:

public class RunCountAtomic {
private static final ReentrantLock lock = new ReentrantLock(true);
public static AtomicInteger aValue = new AtomicInteger(0);

public void runLoop() {
for (int i = 0; i < 5; i++) {
doSomeWork();
aValue.decrementAndGet();
}
printlnValue(aValue.get());
}

private void printlnValue(int value) {
lock.lock();
try {
System.out.println(" Expected value is - (5 x 10 thread = -50) , actual is: " + value);
} finally {
lock.unlock();
}
}

public void doSomeWork() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}

现在保证您最后打印的是 -50

关于java AtomicInteger decrementAndGet 未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61392390/

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