2

Consider the following code:

// Below block executed by thread t1
synchronized(obj) {
   obj.wait(0);
}

// This block executed by thread t2
synchronized(obj) {
    obj.notify();
}

I understand that in above code if t1 has taken ownership of synchronized block and at the same time if thread t2 tries to take synchronized block, then t2 goes for a kernel wait. I want to avoid this situation and spin t2 before the block until t1 calls wait and leaves ownership of the block. Is that possible?

Java Guru
  • 466
  • 4
  • 12
Kiran Prabhu
  • 51
  • 1
  • 1
  • 7
  • Please put more effort into formatting your post before hitting submit - use the preview to see what the post will look like, and only submit it when it looks how you'd want it to look if *you* were answering the question. – Jon Skeet Nov 03 '14 at 07:17
  • 7
    Additionally, do you have evidence that this is actually causing a problem in your code? A spin lock is very rarely the right solution - and bear in mind that `t1` will relinquish the lock as soon as it calls `wait()`, so the window of opportunity for t2 blocking is really very small. – Jon Skeet Nov 03 '14 at 07:20
  • Why do you want to do that? Instead on one thread waiting on the lock, you'd have one thread waiting on the lock, and at the same time wasting CPU cycles. – Thomas Stets Nov 03 '14 at 08:07
  • my use of this code block is too chatty, multiple threads wait and notify, i dont want my thread to go in kernal waits rather i can spin a little and acquire the ownership – Kiran Prabhu Nov 03 '14 at 09:03
  • Agree that the OP should expand on the "why" - but if there was never a good need, then the `java.util.concurrent.locks` package would not have been created. – Erwin Bolwidt Nov 03 '14 at 09:04
  • @ThomasStets probably because of the cargo-cult 'blocking bad, non-blocking good'. – Martin James Nov 03 '14 at 13:54
  • @Erwin that package was created for totally different purposes than to control if and how long a lock spins before making the kernel call (where does it even allow that? Never ran into it). For really good reasons - that's an implementation detail that the JVM can handle perfectly fine on its own. – Voo Nov 03 '14 at 17:29

4 Answers4

3

The JVM need not implement entry to a locked synchronized block as a hard block and context switch. It has the option of using lighter weight methods, such as spin locks. In fact, the Oracle JVM goes to some lengths to avoid blocking. So you might find that the JVM has already done this optimisation for you. And if it has not, that might be because the JVM has evidence that a spin lock would be a bad idea.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
1
import java.util.concurrent.atomic.AtomicBoolean;

public class SpinLock {

   private AtomicBoolean locked = new AtomicBoolean(false);

   public void lock() {
      while (!locked.compareAndSet(false, true));
   }

   public void unlock() {
      locked.set(false);
   }
}
kosotd
  • 47
  • 3
  • No need for CAS to implement a SpinLock. Changing the loop by something like while (getAndSet(true) == true) will probably rely on a more lightly xchg instruction. But there is more to it and probably best to rely on the JVM to do what's right. – MappaM Nov 07 '18 at 15:14
0

Yes, it's possible to do what you want.

An implementation of the interface java.util.concurrent.locks.Lock (such as ReentrantLock) allows you to busy-wait for a lock using the tryLock method (invoked from a loop).

To implement wait and notify functionality, you call the method newCondition on Lock to obtain a Condition object. The Condition interface has the methods await and signal/signalAll that work analogous to wait and notify/notifyAll.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
-3

Its very easy to implement spinlock in Java. The idea here is to take advantage of tryLock() method of Lock interface.

 import java.util.concurrent.locks.ReentrantLock;

public class SpinLock extends ReentrantLock{

public SpinLock() {
  super();
 }


 public void lock() {
  while(!super.tryLock()) {
    // Do Nothing
  }

 }

 public void unlock() {
  super.unlock();
 }

}

Reference: https://tech693.blogspot.com/2018/08/java-spin-lock-implementation.html

Java Guru
  • 466
  • 4
  • 12