Basic Lock Algorithms in Lightweight Thread Environments
Taras Skazhenik, Nikolai Korobenikov, Andrei Churbanov, Anton Malakhov, Vitaly Aksenov
TL;DR
Locking for lightweight thread environments requires careful design because cooperative scheduling can cause deadlocks with OS-thread locks. The authors adapt TTAS and MCS to Argobots and Boost Fibers, integrating yield and suspend via a backoff framework, and propose a TTAS-MCS-N cohort lock to balance performance. Extensive benchmarks reveal that waiting strategy effectiveness and core count strongly influence results, with no single best lock across all settings; the cohort approach often provides robust performance. The work offers practical guidance for library authors and suggests adaptive strategies to optimize mutex behavior across diverse workloads.
Abstract
Traditionally, multithreaded data structures have been designed for access by the threads of Operating Systems (OS). However, implementations for access by programmable alternatives known as lightweight threads (also referred to as asynchronous calls or coroutines) have not been thoroughly studied. The main advantage of lightweight threads is their significantly lower overhead during launch and context switching. However, this comes at a cost: to achieve proper parallelism, context switches must be manually invoked in the code; without these switches, new lightweight threads will never be executed. In this paper, we focus on the simplest multithreaded data structure: a mutex (also known as a lock). We demonstrate that original implementations for OS threads cannot be used effectively in this new context due to the potential for deadlocks. Furthermore, correctness is not the only concern. In certain languages, such as C++, there are various lightweight thread libraries, each with different implementations and interfaces, which necessitate distinct lock implementations. In this work, we present a modification of TTAS and MCS locks for the use from lightweight threads and demonstrate that the two context switch mechanisms of lightweight threads, yielding and sleeping, are crucial. However, the performance of TTAS and MCS may differ significantly depending on the settings. If one wants to have a lock that works well for any library, we suggest using the cohort lock, which strikes a balance between MCS and TTAS by utilizing several MCS queues with a common TTAS.
