0

I was studying about AutomaticInteger. It stated that the use of an AtomicInteger makes an integer operation non-blocking. It is said that the compareAndSet() method of the AtomicInteger makes use of Compare-and-set feature. Compare-and-set feature returns false if it is not successful. To make Compare-and-set successful, compareAndSet() method of the AtomicInteger has to use it in an infinite loop. It is said that since the integer operations are small, it is more beneficial to wait in the loop than to switch the context.

To my understanding, every thread has a fixed time quanta available. If a thread cannot complete its work in its time quanta, it will have to be preempted. Then it will get a chance again later.

So my questions are:

  1. After being unable to gain a lock on the Synchronized method or block, is any thread preempted before its time quanta expire? If yes, when does that thread get CPU time again?
  2. How is a kind of spinlock (infinite loop) present in compareAndSet() method of AtomicInteger class able to reduce the context switch time?
my name is GYAN
  • 1,269
  • 13
  • 27
  • 1.It depends on the thread scheduler. It isn't defined by Java. – user207421 Sep 03 '20 at 04:46
  • 1
    Spin locks and `ai.compareAndSet(...)` both make use of unbounded loops, but there is a crucial difference: After a spin lock succeeds, the lock is _locked_. If the thread that now "owns" the lock takes a long time to do some thing before unlocking it again, then that _blocks_ every other thread that wants to lock the same lock. On the other hand, if one thread happens, by chance, to have perpetual bad luck with `compareAndSet()` it won't prevent other threads from doing their work. That's why we say `compareAndSet()` is "non-blocking:" It doesn't block any _other_ thread. – Solomon Slow Sep 03 '20 at 12:51
  • P.S., "Unbounded" is a better word than "infinite" here. If we call a loop "infinite," we mean that it is _guaranteed_ to never terminate. When we say that a loop is "bounded," we are saying that it is guaranteed not to iterate more than some number of times, where that number is known before the loop is entered. Finally, when we say that it is "unbounded," we're saying that there's no guarantee. The loop will terminate when come condition becomes true, but we are unable to promise if or when that actually will happen. – Solomon Slow Sep 03 '20 at 12:57
  • 2
    @SolomonSlow it’s worth noting that a thread owning a lock still may lose the CPU, holding the lock for an indeterminate time without guilt, until the operating system’s task scheduler (that doesn’t know anything about the lock) assigns it a CPU core again. In contrast, a compare-and-set can only fail if another thread was successful at the same time. – Holger Sep 24 '20 at 15:06

1 Answers1

3

After being unable to gain a lock on the Synchronized method or block, is any thread preempted before its time quanta expire? If yes, when does that thread get CPU time again?

That's up to the scheduler. But if the thread gets pre-empted, it's only because there are other threads that can make immediate forward progress.

How is a kind of spinlock (infinite loop) present in compareAndSet() method of AtomicInteger class able to reduce the context switch time?

It will only loop if the AtomicInteger was modified, in which case that means another thread made forward progress. Two threads can't make forward progress by modifying the very same shared resource at the very same time anyway. If it loops a lot, that means lots of forward progress is being made by other threads. In realistic conditions, it would be extraordinary rare for a thread to spin more than twice and that's still going to be cheaper than an unnecessary context switch.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278