Latin America Regional Special Section
Data and Information

Recent Advances on Principles of Concurrent Data Structures

Concurrent data structures are a key factor in exploiting the inherent parallelism of modern multicore architectures.

Posted
rows of colored lights in space, illustration

Our research group at the Instituto de Matemáticas of the Universidad Nacional Autónoma de México focuses in studying the principles underlying distributed computing, which covers a wide range of services in our everyday life, for example, cloud storage, cryptocurrencies, collaborative editing, as well as concurrent software that governs modern multicore computers. The goal of our discussion here is to survey our recent advances on one of our research lines: concurrent data structures. This type of data structures has attracted a great deal of interest as they are a key factor to exploit the inherent parallelism in modern multicore architectures, ubiquitous since the beginning of this century (see for example Herlihy10 and Shavit12).

In a concurrent implementation of a data structure, a pool of threads modify the contents of the structure at unpredictable times, since they run asynchronously, through the operations provided by the data structure. Furthermore, the operations of different threads might overlap in time, because the threads themselves need to implement the data structure using the underlying coordination primitives provided by the operating systems, such as read/write on shared registers, compare set, and others. See Figure 1 for an example of an execution of a concurrent stack with three threads.

Figure 1.  A linearizable stack execution for three threads, T1, T2 and T3. Horizontal double-headed arrows denote the time that elapses between the invocation and response of a thread’s operation.

How do we know that a concurrent implementation of a stack is correct? What do we even mean by a “concurrent stack?” What do we mean by a “queue” if several threads can enqueue an item concurrently? In the classic case of sequential implementations there is a unique, “natural” definition of a data structure such as a queue or a stack. In contrast, in the concurrent world, this is not always the case, one can define correctness of concurrent implementations in several different ways, each of them useful in different applications.

The gold standard of correctness condition for concurrent implementations is linearizability.11 Linearizability states that every operation appears as if it takes effect “instantaneously” at a unique point in time between its invocation and response. These sequence of linearization points induce a sequential execution of the operations, and the execution is correct, or linearizable, if there are linearization points that induce a sequential execution that satisfies the sequential specification of the object implemented. Figure 1 shows linearization points that induce a valid stack sequential execution.

Linearizability is so popular because of its practical usefulness and its theoretical properties. From the practical side, for example, it allows the design of concurrent software in a modular manner, which is key for the design and implementation of large-scale systems. Namely, if one designs independently two linearizable objects, it is guaranteed a system that uses both is also linearizable.

Despite all its benefits, after years of research, it is now well understood that linearizability has some inherent limitations. We provide two examples. There are concurrent data structures that cannot be analyzed through linearizability, since they do not have a sequential specification. For example, the exchanger object in the concurrent package of Java, which serves as a synchronization point where threads exchange items concurrently, has no sequential specification, because in sequential executions no exchanges take place. A second example is that it has been formally shown that some common data structures, such as sets, queues, stacks, and work-stealing for dynamic load balancing, only admit linearizable implementations that are inherently slow, for example Attiya et al.1

In the past few years, part of the research in our group has been devoted to developing techniques to overcome the limitations of linearizability. We proposed an extension of linearizability, called interval-linearizability, that is expressive enough to specify data structures that are impossible to specify with linearizability5,6 (such as the exchanger object); hence one can, for the first time, formally reason about correctness for them. These types of structures are “truly” concurrent, which is forbidden in linearizable specifications and implementations.

Generally, in an interval-linearizable implementation, every operation takes effect “continuously” in an interval of time, instead of instantaneously at a single point. During the interval, the operation might affect, or be affected by, the other operations whose linearization intervals it overlaps with, which is the mechanism that allows truly concurrent behaviors to be specified. Figure 2 depicts an example of an execution of a counter with an interval-linearizable query operation. Thus, linearizability is nothing else than interval-linearizability when all intervals are just points.

Figure 2.  An interval-linearizable execution of a relaxed counter for three threads, T1, T2 and T3. Operation update, which adds a natural number to the current state of the counter, is linearizable, namely, it always takes effect at a single point. In contrast, operation query takes effect at an interval of time, returning a value that lies in the interval of integers defined by the state of the counter before and after the linearization interval of the operation.

The interval-linearizability condition allowed us to formally specify new relaxed variants of classic data structures, such as queues and stacks and work-stealing, and provide simple and efficient implementations,7 some of them delivering a good performance when combined with solutions to practical parallel problems.4

A challenging task by itself is that of proving linearizability of an implementation, due to the large number of possible executions implementations can exhibit (it has been formally shown that deciding if a finite execution is linearizable is NP-complete, for some concurrent objects9). The formal verification community has provided different techniques to tackle this problem, each of them providing different levels of guarantees. Despite all efforts, proving linearizability remains challenging. Our group has explored new static and dynamic techniques that help with this task. We have proposed new static techniques for modular formal verification of concurrent implementations,3 as well as dynamic verification algorithmic approaches2,8 that test at runtime whether the current execution of an implementation is linearizable, and possibly prevent side effects in case of non-linearizable executions.

    • 1. Attiya, H. et al. Laws of order: Expensive synchronization in concurrent algorithms cannot be eliminated. In Proceedings of the 38th ACM SIGPLAN-SIGACT Symp. Principles of Programming Languages. Ball, T., and Sagiv, M. (Eds.),  Austin, TX, USA, Jan. 26–28, 2011, 487498.
    • 2. Bonakdarpour, B. et al. Decentralized asynchronous crash-resilient runtime verification. J. ACM 69, 5 (2022), 34:134:31.
    • 3. Castañeda, A., Hurault, A., Quéinnec, P., and Roy, M. Tasks in modular proofs of concurrent algorithms. Inf. Comput. 292, (2023), 105040.
    • 4. Castañeda, A. and Piña, M.  Read/write fence-free work-stealing with multiplicity. J. Parallel Distributed Comput. 186, (2024), 104816.
    • 5. Castañeda, A., Rajsbaum, S., and Raynal, M. Unifying concurrent objects and distributed tasks: Interval-linearizability. J. ACM 65, 6 (2018), 45:145:42.
    • 6. Castañeda, A., Rajsbaum, S., and Raynal, M. A linearizability-based hierarchy for concurrent specifications. Commun. ACM 66, 1 (Jan. 2023), 8697.
    • 7. Castañeda, A., Rajsbaum, S., and Raynal, M. Set-linearizable implementations from read/write operations: Sets, fetch & increment, stacks and queues with multiplicity. Distributed Comput. 36, 2 (2023), 89106.
    • 8. Castañeda, A. and Rodríguez, G.V.  Asynchronous wait-free runtime verification and enforcement of linearizability. In Proceedings of the 2023 ACM Symp. Principles of Distributed Computing (2023), 90101.
    • 9. Gibbons, P.B. and Korach, E. Testing shared memories. SIAM J. Comput. 26, 4 (1997), 12081244.
    • 10. Herlihy, M. and Shavit, N. The Art of Multiprocessor Programming. Morgan Kaufmann, 2008.
    • 11. Herlihy, M. and Wing, J.M.  Linearizability: A correctness condition for concurrent objects. ACM Trans. Program. Lang. Syst. 12, 3 (1990), 463492.
    • 12. Shavit, N. Data structures in the multicore age. Commun. ACM 54, 3 (Mar. 2011), 7684.

Join the Discussion (0)

Become a Member or Sign In to Post a Comment

The Latest from CACM

Shape the Future of Computing

ACM encourages its members to take a direct hand in shaping the future of the association. There are more ways than ever to get involved.

Get Involved

Communications of the ACM (CACM) is now a fully Open Access publication.

By opening CACM to the world, we hope to increase engagement among the broader computer science community and encourage non-members to discover the rich resources ACM has to offer.

Learn More