gpt4 book ai didi

java - Java Spring多线程原子性问题

转载 作者:行者123 更新时间:2023-12-03 13:11:49 26 4
gpt4 key购买 nike

我有一个类

@Component
public class JmxConf implements Serializable {
private static final long serialVersionUID = 5586922486161726170L;

private AtomicInteger count = new AtomicInteger(0);

public AtomicInteger getCount() {
return count;
}
}

然后我将这个类自动连线到另一个
@Component
public class QueueListener {
private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

@Autowired
private JmxConf jmxConf;


public doIt(){
if(jmxConf.getCount().get()>.....) {

jmxConf.getCount().incrementAndget();

......
executor.submit(new thread here);

jmxConf.getCount().decrementAndget();
}
}
}

我们有一个具有状态的单例bean,但是对该状态的访问由原子变量控制。此类是否是线程安全的?如果没有,为什么。谢谢

最佳答案

不,这不会是原子的。您在这里参加比赛:

if(jmxConf.getCount().get()>.....) {

jmxConf.getCount().incrementAndget();

想象一下 greater than是某个数字,只说10的情况。
if(jmxConf.getCount().get() > 10) { 

jmxConf.getCount().incrementAndget();

如果该线程达到 if时值为9,该怎么办?当达到该增量时,另一个线程已将其递增为10,现在将其递增为11。

您应该使用compareAndSet。
while(true){
int value = jmxConf.getCount().get() + 1;
if(value > 10){
break;
}
if(mxConfg.getCount().compareAndSet(value-1, value){
executor.submit(new thread here);
jmxConf.getCount().decrementAndGet();
break;
}
}

您可以阅读有关Java提供的原子引用和 compareAndSet的更多信息。

那么,为什么我们需要 while(true)呢? compareAndSet函数 takes two parameters
public final boolean compareAndSet(int expect, int update)

该方法说:“尝试在线程安全的情况下更新AtomicInteger,这是我希望当前使用的值,这是我要使用其更新的值。如果在尝试进行更新时,则使用我期望AtomicInteger可以比您放心地进行更新。如果不是我期望的更新,请不要更新它,并通知我您没有更新。”

假设我们输入了 if,如果另一个线程也在尝试以5的值更新AtomicInteger,则该值为5,两个线程的参数期望都为5。因为它是线程安全的,所以只有一个线程可以获胜,这意味着一个线程将失败(compareAndSet在失败时将返回false)。在这种情况下,我们应该重试compareAndSet,直到成功或超过 break的阈值为止。

关于java - Java Spring多线程原子性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29773905/

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