Overview
Lincheck is a framework for testing concurrent code on the JVM. When running tests, Lincheck explores the potential thread interleavings of the program and reports the ones that lead to incorrect behavior.
A concurrency test in Lincheck only requires you to list the operations for each thread and the expected assertions. Lincheck handles the rest:
If the test fails, Lincheck provides the thread interleaving and the thread switch points that led to an error:
How Lincheck works
Each time the JVM runs concurrent code, the execution order of the operations across threads might change. For example, an operation can be interrupted by another operation in a different thread. This is not an error by itself, but can lead to an error if the code has concurrency bugs.

Lincheck implements two testing strategies to find execution schedules that lead to incorrect behavior:
Model checking. Lincheck controls scheduling by inserting explicit thread switch instructions into the program. These instructions are placed at synchronization points or shared memory accesses. Model checking enables Lincheck to generate an exact execution trace that leads to an error.
Stress testing. The operating system controls scheduling. Lincheck executes each scenario multiple times to increase the chances of finding an error.
Explore Lincheck
Learn Lincheck features step-by-step in the Getting started with Lincheck.
Learn about the declarative approach to testing concurrent data structures in the Testing strategies article.
Learn more
"How we test concurrent algorithms in Kotlin Coroutines" by Nikita Koval: Video. KotlinConf 2023
"Lincheck: Testing concurrency on the JVM" workshop by Maria Sokolova: Part 1, Part 2. Hydra 2021
"Lincheck: A Practical Framework for Testing Concurrent Data Structures on JVM" by Nikita Koval et al.: Paper. 2023