Using anonymous runnable class code goes in deadlock state but with lambda it works fine

anonymous-class, java, java-8, lambda, multithreading

Solution

Decompiling with `javap` the inner class shows the following for the `run` method:

public void run();
  descriptor: ()V
  flags: ACC_PUBLIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0
       1: getfield      #12                 // Field this$0:Ltest/ThreadCreationTest;
       4: invokestatic  #22                 // Method test/ThreadCreationTest.access$0:(Ltest/ThreadCreationTest;)V
       7: return
    LineNumberTable:
      line 31: 0
      line 32: 7
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       8     0  this   Ltest/ThreadCreationTest$1;

Notice that there is a static synthetic method `access$0` which in turn calls the private method `call`. The synthetic method is created because `call` is private and as far as the JVM is concerned, the inner class is just a different class (compiled as `ThreadCreationTest$1`), which cannot access `call`.

static void access$0(test.ThreadCreationTest);
  descriptor: (Ltest/ThreadCreationTest;)V
  flags: ACC_STATIC, ACC_SYNTHETIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0
       1: invokespecial #68                 // Method call:()V
       4: return
    LineNumberTable:
      line 51: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature

Since the synthetic method is static, it is waiting for the static initializer to finish. However, the static initializer is waiting for the thread to finish, hence causing a deadlock.

On the other hand, the lambda version does not rely on an inner class. The bytecode of the constructor relies on an `invokedynamic` instruction (instruction #9) using `MethodHandles`:

public test.ThreadCreationTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=1
         0: aload_0
         1: invokespecial #13                 // Method java/lang/Object."<init>":()V
         4: new           #14                 // class java/lang/Thread
         7: dup
         8: aload_0
         9: invokedynamic #19,  0             // InvokeDynamic #0:run:(Ltest/ThreadCreationTest;)Ljava/lang/Runnable;
        14: invokespecial #20                 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
        17: astore_1
        18: aload_1
        19: invokevirtual #23                 // Method java/lang/Thread.start:()V
        22: aload_1
        23: invokevirtual #26                 // Method java/lang/Thread.join:()V
        26: goto          36
        29: astore_2
        30: invokestatic  #29                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
        33: invokevirtual #33                 // Method java/lang/Thread.interrupt:()V
        36: return

Problem

I am trying to find out the cause behind below mentioned code. Here if I create Thread using anonymous inner class it goes into deadlock state but with lambda expressions it works fine. I tried to find the reason behind this behavior but I could not. ``` public class ThreadCreationTest { static { new ThreadCreationTest(); } private void call() { System.out.println("Hello guys!!!"); } public ThreadCreationTest() { // when we use this thread it goes in deadlock kind of state Thread thread1 = new Thread(new Runnable() { public void run() { call(); } }); // This one works fine. Thread thread = new Thread(() -> call()); thread.start(); try { thread.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static void main(String... args) { System.out.println("Code finished..."); } } ``` with lambda expression output : ``` Hello guys!!! Code finished... ``` with anonymous class : ``` code goes into deadlock state ```

Original source