简体   繁体   中英

Java spring multithreading atomic issue

I have a class

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

  private AtomicInteger count = new AtomicInteger(0);

  public AtomicInteger getCount() {
    return count;
  }
}

And I autowired this class to another

@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();
    }
  }
}

We have one singleton bean which has a state but access to this state is controlled by an atomic variable. Will this class be thread-safe? And if not, why. Thanks

No it won't be atomic. You have a race here:

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

  jmxConf.getCount().incrementAndget();

Imagine the scenario where the greater than is some number, just say 10.

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

  jmxConf.getCount().incrementAndget();

What if, when the thread hits the if the value is 9 . When it gets to the increment it was already incremented by another thread to 10 and now you increment it to a value of 11 .

You should use 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;
   }
} 

You can read more on atomic references and compareAndSet offered by Java.


So why do we need the while(true) ? The compareAndSet function takes two parameters

public final boolean compareAndSet(int expect, int update)

The method says "Try to update the AtomicInteger in a thread safe matter, here is the value I expect it to be currently and here is the value I want to update it with. If, when trying to do the update, the value of the AtomicInteger is what I expect than you can safely do the update. If it's not what I expect it to be then don't update it and notify me that you didn't update it."

Let's say we enter the if and the value is 5 if another thread is also trying to update the AtomicInteger with a value of 5 both threads will have an expectation of 5 as the parameter. Because it is thread-safe only one thread can win which means one will fail (the compareAndSet will return false on failure). In that case we should re-try the compareAndSet until we succeed or exceed the threshold in which we break .

AtomicInteger是线程安全的,因此这将是线程安全的。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM