Fundamentals 20 min read

Understanding Kotlin Coroutines, Go Coroutines, and JVM Threading

The article demonstrates that Kotlin coroutines on the JVM are merely a convenient API layered on traditional Java threads rather than true lightweight coroutines, contrasting them with Go’s M:N goroutine scheduling, and discusses experimental Kotlin‑Native and OpenJDK Loom projects that aim to provide genuine coroutine support.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Understanding Kotlin Coroutines, Go Coroutines, and JVM Threading

Most online articles claim that Kotlin coroutines are highly efficient and outperform threads, but this article investigates whether that claim holds true.

Coroutines are not a new concept; a basic coroutine model can be implemented in C++ with less than 50 lines of code. The article adopts the definition of coroutines mainly from Go, as the concept has become popular after Go's rise.

1. Mainstream definition of Kotlin coroutines on the Internet

The discussion originates from a WeChat article titled "After Go, is Java still the best choice?" The author wonders whether Kotlin truly implements a coroutine mechanism similar to Go's, or if the numerous blog posts are misleading.

2. Relationship between JVM Thread and OS Thread

In most JVM implementations (Oracle JVM, Android ART), a Java Thread maps 1:1 to an OS thread. Each Thread consumes about 1 MB of memory, and context switches introduce overhead. The article shows the native JNI call chain that creates a thread, with screenshots of the source files ( Thread.c, jvm.cpp, and Linux-specific os_linux.cpp).

3. What Go does with coroutines

Go schedules many goroutines onto a small number of OS threads (M:N model). Each goroutine uses only about 4 KB of stack, far less than a Java thread. The article provides a Go example that launches ten goroutines, each printing its thread ID, demonstrating that many concurrent tasks can run on a single thread.

package main

import (
    "fmt"
    "runtime"
    "strconv"
    "time"
    "golang.org/x/sys/windows"
)

func name(s string) {
    for {
        // sleep 1s for readability
        time.Sleep(time.Second)
        str := fmt.Sprint(windows.GetCurrentThreadId())
        var s = "iqoo" + s + " belong thread " + str
        fmt.Println(s)
    }
}

func main() {
    fmt.Println("逻辑cpu数量:" + strconv.Itoa(runtime.NumCPU()))
    str := fmt.Sprint(windows.GetCurrentThreadId())
    fmt.Println("主协程所属线程id =" + str)
    for i := 1; i <= 10; i++ {
        go name(strconv.Itoa(i))
    }
    time.Sleep(100 * time.Second)
}

4. Java vs Go concurrency

The article shows a minimal Java program that starts two threads, each printing a message in an infinite loop, illustrating that Java relies on OS threads for concurrency.

package com.wuyue;

public class JavaCode {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("iqoo  " + Thread.currentThread().getName());
                    try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("x27  " + Thread.currentThread().getName());
                    try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
                }
            }
        }.start();
    }
}

In Go, the same logical tasks are handled by many goroutines on far fewer OS threads, confirming the M:N scheduling advantage.

5. Does Kotlin-JVM provide true coroutines?

The article argues that Kotlin-JVM cannot achieve the same coroutine capabilities as Go. Kotlin’s coroutine support on the JVM is essentially a wrapper around Java threads, relying on synchronized and other Java synchronization primitives.

6. Locks in Kotlin

Kotlin does not introduce its own lock keyword; it uses Java’s synchronization mechanisms. The article shows a Kotlin class using the @Synchronized annotation and decompiles it to reveal the underlying Java bytecode.

class PrintTest {
    @Synchronized fun print() {
        println("hello world")
    }
    @Synchronized fun print2() {
        println("hello world")
    }
}

7. Future of coroutines in Kotlin

Kotlin‑Native, which compiles Kotlin to native binaries, offers a worker model that can provide true coroutine-like concurrency, though it is still experimental and only supports Linux and macOS.

8. JVM plans for coroutines

Projects like Quasar (bytecode injection) and OpenJDK’s Loom aim to bring lightweight coroutine support to the JVM.

9. What Kotlin coroutines actually are

On the JVM, Kotlin coroutines are essentially a more convenient API over Java threads, using the suspend keyword to mark functions that must be called from a coroutine context. They simplify asynchronous code but do not eliminate thread usage.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            getInfo()
            getInfoNoContext()
            Log.v("wuyue", "我又切回来了 in thread " + Thread.currentThread().name)
        }
    }

    suspend fun getInfo() {
        withContext(Dispatchers.IO) {
            Log.v("wuyue", "getInfo in thread " + Thread.currentThread().name)
        }
    }

    suspend fun getInfoNoContext() {
        Log.v("wuyue", "getInfoNoContext in thread " + Thread.currentThread().name)
    }
}

10. Summary

Kotlin-JVM coroutines are essentially wrappers around Java threads, not true lightweight coroutines.

Their "suspend" behavior merely offloads work to another thread without blocking the original one.

Kotlin‑Native may eventually provide genuine coroutine support.

For Java developers, the number of OS threads equals the number of JVM threads unless a custom runtime (e.g., Loom) is used.

OpenJDK Loom is the most promising effort to bring true coroutine semantics to the JVM.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMperformanceGoKotlinThreadCoroutines
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.