Fact-checked by Grok 2 weeks ago

Sequential consistency

Sequential consistency is a memory consistency model used in systems, such as multiprocessors and environments, that guarantees the outcome of any execution matches the result of executing all processes' operations in some single, global sequential order while preserving the program-specified order within each individual process. Introduced by in 1979, this model provides a strong guarantee of correctness by ensuring that all accesses appear and that writes to different locations are observed in the same order by all processors. Formally, a system achieves sequential consistency if the "precedes" relation among operation executions forms a total ordering, even for concurrent events across processes, effectively interleaving their references in a way that mimics a sequential program execution. This property simplifies reasoning about concurrent programs by eliminating non-intuitive reorderings, making it equivalent to one-copy in database systems. However, implementing sequential consistency imposes significant performance overhead, as it restricts hardware optimizations like , write buffering, and code motion that could violate the strict ordering. In practice, sequential consistency is often relaxed in modern architectures—such as those using total store order (TSO) or weaker models like processor —to improve performance, with programmers relying on explicit synchronization primitives like memory fences or atomic instructions to enforce necessary orders. Despite these trade-offs, it remains a foundational for evaluating weaker consistency models, as violations can lead to subtle bugs in concurrent algorithms, such as incorrect producer-consumer interactions where a might observe an updated pointer but not the corresponding data.

Definition and Background

Core Definition

Sequential consistency (SC) is a memory consistency model used in systems, particularly in multiprocessor environments, where it ensures that the results of a program's execution are equivalent to some sequential interleaving of the operations from all participating processes. Under SC, all memory operations—such as reads and writes—appear to execute atomically and in a single global that respects the program order on each individual . This means that the overall execution behaves as if all memory accesses from different processes were serialized into one sequential , even though the operations may overlap in time due to parallelism. The program order requirement is central to SC: on any single , the sequence of memory operations must occur in the exact order specified by the program's instructions, preserving dependencies and within that processor's thread of execution. This per-processor ordering is then preserved within the global , ensuring that no operation from one processor is reordered relative to another in a way that violates the intended semantics. For instance, if a processor issues a write followed by a read, the write must precede the read in the global sequence, and similarly across all processors. This model provides programmers with a straightforward for reasoning about concurrency, as if the system were executing operations one at a time in some valid interleaving. From the perspective of any observer or , SC guarantees that the execution appears sequential and atomic, eliminating surprises from out-of-order completions that could arise in weaker consistency models. This global serialization fosters intuitive program correctness in shared-memory systems, where developers can assume a linear history of events without needing to account for hardware-level optimizations that might otherwise obscure the order. While SC is intuitive, implementing it can impose performance costs on hardware, as it restricts aggressive reordering of operations.

Origins in Concurrent Programming

Sequential consistency emerged during the and amid the development of shared-memory multiprocessor systems, which aimed to enhance performance through but introduced complexities in memory access coordination. Early multiprocessors, such as those from in the early , relied on to allow multiple processors to access common data, but naive implementations assuming atomic operations often failed to handle concurrent accesses properly, resulting in unpredictable program behaviors. This period marked a shift from uniprocessor systems, where sequential execution was inherent, to multiprocessors requiring explicit models to maintain correctness in parallel environments. A primary challenge addressed by sequential consistency was the violation of programmer expectations due to hardware optimizations in these systems. Techniques like write buffering, intended to improve performance by allowing to continue execution while writes were pending, could reorder operations and lead to conditions or incorrect results. For instance, in algorithms such as Dekker's , a write buffer might delay a write to a variable, enabling a subsequent read on another to see stale and permit simultaneous entry, contrary to the intended sequential semantics. Without a consistent model, such optimizations disrupted the intuitive ordering assumed from uniprocessor experience, complicating debugging and verification. Early recognition of these issues appeared in parallel computing literature, emphasizing the need for a straightforward model that preserved intuition while accommodating realities. Researchers highlighted that weaker models, which permitted greater flexibility for optimizations like , increased the burden on software developers to manage ordering explicitly. Sequential consistency was positioned as an accessible alternative, providing a global view of operations that aligned with sequential program reasoning without overly restricting design. Initial discussions in the centered on ensuring "as-if" sequential execution to simplify concurrency reasoning. This concept posited that multiprocessor executions should behave equivalently to some interleaving of individual process operations in program order, making it easier for programmers to verify correctness as in single-threaded code. Such foundational ideas laid the groundwork for later formalizations, addressing the core tensions between performance and reliability in emerging multiprocessor architectures.

Formalization

Operational Model

In the operational model of sequential consistency (SC), an execution is defined as sequentially consistent if there exists a over all memory operations from all processors such that two conditions hold: first, the operations issued by each individual processor appear in the program order specified by that processor's code; second, every read operation returns the value written by the most recent write operation to the same location in this . This model simulates as if all operations are serialized into a single global sequence, preserving the illusion of a uniprocessor execution despite concurrency. To illustrate, consider a simple two-processor scenario where processor P1 executes the sequence write(x, 1); write(y, 1); and processor P2 executes r1 = read(y); r2 = read(x);, assuming initial values x=0 and y=0. A valid SC execution trace might interleave as follows, with operations labeled by processor and step:
  • P1: write(x, 1)
  • P1: write(y, 1)
  • P2: r1 = read(y) // returns 1, as it follows the write to y
  • P2: r2 = read(x) // returns 1, as it follows the write to x
This trace respects SC because a —write(x,1) by P1, write(y,1) by P1, read(y) by P2, read(x) by P2—preserves P1's program order (write x before write y) and P2's order (read y before read x), with each read observing the latest preceding write in the order. An invalid trace under SC would be one where r1=1 and r2=0, as no total order can satisfy the conditions: if read(y) sees write(y,1), then write(y,1) precedes read(y) in the total order; since write(x,1) precedes write(y,1) in P1's program order, write(x,1) also precedes read(y); moreover, read(y) precedes read(x) in P2's program order, so write(x,1) precedes read(x), forcing r2=1. Verification of SC in an observed execution trace proceeds step-by-step as an operational simulation. First, extract the partial of operations per from the , enforcing order (e.g., no later operation from a processor precedes an earlier one). Second, attempt to construct all possible s by interleaving these partial orders across processors. Third, for each candidate total order, simulate the memory state sequentially: process writes to update s and ensure each read retrieves the from the last write to that location preceding it in the order. If at least one such total order matches the observed read values without contradiction, the trace is SC-compliant; otherwise, it violates SC. This process can be implemented in for automated checking, as shown below for a trace with operations O = {o1, o2, ..., on} labeled by processor, type (read/write), location, and value:
function isSC(execution_trace):
    partial_orders = group_operations_by_processor(execution_trace)  // Enforce program order per [processor](/page/Processor)
    candidate_orders = generate_interleavings(partial_orders)  // All total orders respecting partials
    for each total_order in candidate_orders:
        [memory](/page/Memory) = initialize_memory_to_defaults()
        valid = true
        for each op in total_order:
            if op is write(loc, val):
                [memory](/page/Memory)[loc] = val
            else if op is read(loc):
                observed_val = execution_trace[op].returned_value
                if observed_val != [memory](/page/Memory)[loc]:
                    valid = false
                    break
        if valid:
            return true  // At least one matching [serialization](/page/Serialization)
    return false  // No valid [serialization](/page/Serialization)
This operational approach provides a trace-based simulation for validating SC, distinct from axiomatic methods that use logical predicates to check properties directly.

Axiomatic Specification

Sequential consistency can be formally specified axiomatically through a set of logical conditions that characterize valid executions of concurrent programs. An execution is sequentially consistent if it satisfies three key conditions: (1) the operations of each individual processor occur in the program order (PO) specified by its program; (2) there exists a (TO) on all memory operations across all processors that respects and extends the PO for each processor; and (3) every read operation returns the value written by the most recent write to the same location in the TO. Verification of sequential consistency in an execution can be achieved by checking for the absence of cycles in a dependency graph constructed from the operations. Specifically, the graph includes edges from PO; reads-from relations (rf, linking each read to the specific write whose value it returns); coherence orders (co, a total order on all writes to the same location, reflecting the order in which writes become visible); and from-read relations (fr, linking a read r observing write w to all subsequent writes w' on the same location such that w <_co w'). An execution is sequentially consistent if this combined graph (\PO \cup \rf \cup \co \cup \fr) is acyclic, as cycles would indicate an impossibility of extending to a consistent total order. The precise condition for reads in the total order is given by the following formula: for a sequence of operations o_1, o_2, \dots, o_n ordered by TO, and for every read r, \value(r) = \value(w) \quad \text{where} \quad w = \max \{ w' \mid w' <_{\TO} r \land w' \text{ writes to } \loc(r) \}. This ensures that each read retrieves the value from the latest preceding write in the global order, preventing anomalies like reading stale or future values.

Key Properties and Implications

Sequential Order Guarantee

Sequential consistency provides a guarantee that all operations across multiple processors appear to execute in a single, global sequential order that is consistent with the program order on each individual processor. This means that the interleaving of operations from different processors is observed identically by all processors, as if all operations were executed one at a time through a centralized point. This order guarantee eliminates reordering anomalies, such as out-of-order reads or writes, by enforcing that no operation can be perceived as occurring before or after in a way that violates the global sequence. For instance, sequential consistency prevents the store buffering anomaly, where a processor's write might not be immediately visible to another processor's read due to local buffering, ensuring that writes are observed in the order they were issued relative to subsequent reads. The benefits of this guarantee include simplified and of concurrent programs, as developers can reason about executions as if they occur sequentially, without needing to account for hardware-level reorderings or buffering effects. This intuitive model allows programmers to focus on logical correctness rather than low-level memory behaviors. In terms of implications for program correctness, sequential consistency imposes a predictable total global order on all memory operations, preventing reordering anomalies like store buffering that could lead to unexpected outcomes in weaker models, but does not eliminate data races or guarantee fresh values without . By imposing a total global order, it resolves potential conflicts in a predictable manner, promoting reliable outcomes for synchronized operations.

Impact on Program Correctness

Sequential consistency (SC) ensures that concurrent programs execute as if their operations were interleaved in some sequential order consistent with each program's , thereby preserving the correctness of programs that are valid under purely sequential execution. This model guarantees that invariants, such as in critical sections protected by locks, hold across multiprocessor executions because all operations appear and globally ordered. As a result, developers can reason about program behavior using familiar sequential semantics without worrying about reordering artifacts disrupting logical dependencies. A key application of SC lies in the data race free (DRF) guarantee prevalent in modern programming language memory models, where the absence of data races—defined as concurrent conflicting accesses without proper synchronization—ensures that all executions behave as if under SC. This implies that correctly synchronized programs maintain sequential correctness, while racy programs may exhibit undefined behavior, allowing hardware and compiler optimizations without compromising safe code. For instance, languages like Java and C++ leverage this DRF-SC property to provide intuitive guarantees for race-free code while permitting weaker semantics elsewhere. Despite these benefits, SC has limitations in preventing all forms of concurrency errors, as it does not inherently eliminate data races arising from unsynchronized non-atomic reads and writes, which can interleave in ways that violate expectations even under a . must therefore employ explicit mechanisms, such as locks or barriers, to enforce and avoid such races, as SC alone provides no protection against them. Enforcing SC also imposes performance trade-offs by restricting hardware optimizations, such as instruction reordering, , and relaxed protocols, which are essential for high-throughput multiprocessors but incompatible with SC's strict global ordering requirements. In high-contention scenarios, these constraints can lead to bottlenecks, reducing overall system speed compared to weaker models that allow more aggressive optimizations.

Comparisons with Other Models

Versus Linearizability

Sequential consistency (SC), introduced by in 1979, ensures that operations on a appear to execute in some sequential order consistent with each process's program order, but it permits operations to complete out of real-time order. In contrast, , defined by Maurice Herlihy and in 1990, imposes stricter requirements by mandating that operations appear atomic and respect real-time ordering, meaning no two operations overlap in a way that one completes after the other begins without the later one seeing the effects of the earlier. The key difference lies in atomicity and timing: SC provides a global sequential order without enforcing real-time precedence, allowing concurrent operations to interleave in ways that violate physical time, whereas linearizability treats high-level operations (like reads and writes on objects) as indivisible units that take effect instantaneously at some point between invocation and response, preserving the partial order defined by real-time. For instance, under SC, a read operation might return a stale value even if it completes after a concurrent write has begun, as long as the overall history matches some legal sequential execution; linearizability forbids this for atomic objects, ensuring the read sees the write's effect if the read starts after the write completes. In terms of strength, linearizability is strictly stronger than SC: every linearizable execution is sequentially consistent, since the real-time order refines the sequential order, but the converse does not hold, as demonstrated by histories that are sequentially consistent yet violate real-time constraints. This hierarchy implies that systems achieving linearizability automatically satisfy SC, but implementing SC allows for more relaxed and potentially more efficient behaviors in non-real-time-sensitive scenarios.

Versus Total Store Order

Sequential consistency (SC) requires that all memory operations appear to execute in a single global total order that respects the program order of each , ensuring that writes are immediately visible to subsequent reads across all processors. In contrast, total store order (TSO), a weaker consistency model, permits the use of per-processor write buffers to improve performance, allowing stores to be buffered locally before committing to the global memory, which delays their visibility to other processors. This store buffering in TSO violates SC by enabling scenarios where a write from one processor is not immediately seen by others, and it allows store-load reordering but forbids load-load, load-store, and store-store reordering. A key weakness of TSO is its allowance for store-load reordering, where a can perform a load that bypasses its own pending store in the write buffer, potentially observing an outdated value from another before seeing its own write. For example, consider two threads where Thread 1 executes a = 1 followed by r1 = b, and Thread 2 executes b = 1 followed by r2 = a, starting with a = b = 0; under SC, it is impossible for both r1 = 0 and r2 = 0, but TSO's buffering can produce this outcome if each thread's load sees the initial value before its own store drains to . This anomaly highlights how TSO can lead to counterintuitive behaviors not possible under SC. TSO can approximate SC behavior through explicit synchronization mechanisms, such as memory fences (e.g., MFENCE on x86 or MEMBAR on ), which force the write buffer to drain and prevent reordering across the fence, effectively enforcing a for subsequent operations. TSO serves as the default memory model for and x86 architectures, optimizing for hardware efficiency but often resulting in subtle bugs in code written assuming SC, where relaxed ordering exposes races or incorrect dependencies that pass under stricter models.

Examples and Applications

Simple Multiprocessor Example

To illustrate in a shared-memory multiprocessor, consider a simple setup with two processors, P1 and P2, accessing shared variables A and B, initially set to 0. P1 executes the operations A = 1 followed by B = 1, while P2 performs reads rB = B followed by rA = A, potentially assigning values to a based on the results (e.g., if rB == 0 then X = 1; if rA == 0 then X = 3). Under , as defined by Lamport, the execution must appear as a single global sequential interleaving of all operations that respects each processor's program order. A valid trace under SC might interleave the operations as follows: P1's A = 1, P1's B = 1, P2's = B (yielding 1), P2's = A (yielding 1). Here, P2 observes both new values, consistent with the global order where P1's writes complete before P2's reads, preserving the "happens-before" relation from P1's program order. Another valid trace could have P2's reads occur before any of P1's writes, yielding = 0 and = 0. In both cases, the outcome aligns with some sequential execution of the combined operations. An invalid outcome under occurs if P2 reads rB = 1 (new B) but then rA = 0 (old A), a classic forbidden outcome under where P2 observes an inconsistent partial update from P1, violating the required total global . This is forbidden because seeing B = 1 implies P1's B = 1 has executed after A = 1 in the sequence, so rA must also see A = 1, as P2's read of A follows its read of B. Such an outcome would mean P2 observes only part of P1's updates out of order, breaking the sequential . SC's guarantees enable correct implementation of synchronization primitives like . A variant of for two processes demonstrates this, using shared flags to ensure only one enters the . The below shows the entry protocol (dekkersignal sets need[me] = false and turn = other after exiting):
type processid = 0..1;
var need: array [processid] of boolean;  // initially false
    turn: processid;  // initially 0 or 1

procedure dekkerentry(me: processid);
var other: processid;
begin
    other := 1 - me;
    need[me] := true;
    while need[other] do begin
        if turn = other then begin
            need[me] := false;
            while turn = other do skip;
            need[me] := true;
        end;
    end;
end;
Under , this preserves because all reads and writes (to need and turn) appear in a global sequential order respecting program orders, preventing both processes from simultaneously satisfying the while condition and entering the . For instance, if P1 sets need = true and then checks need, ensures visibility of P2's writes in a consistent , avoiding races that could allow concurrent entry. In weaker models like Total Store Order (TSO), the irrevocable anomaly may occur due to store buffering, potentially breaking without additional fences.

Use in Distributed Systems

In distributed systems, sequential consistency is typically emulated through protocols that enforce a global on operations across nodes, often using replicated state machines (RSMs). In an RSM, all start from the same initial state and process the same sequence of client requests in the same order, ensuring that their outputs remain identical and consistent despite concurrent executions or failures. Consensus algorithms such as and underpin this emulation by achieving agreement on the order of operations; for instance, 's state machine safety property guarantees that if one applies a log entry at a given index, no other applies a conflicting entry, thereby providing sequential consistency for the replicated state. While two-phase commit protocols can support atomicity in distributed transactions to contribute to overall consistency, they are more commonly combined with locking mechanisms rather than directly emulating full sequential consistency due to their focus on commit coordination rather than operation ordering. Sequential consistency finds key applications in distributed databases, where the serializable isolation level ensures that concurrent transactions appear to execute in some sequential , equivalent to sequential consistency in the context of transactional semantics. This prevents anomalies like lost updates or non-repeatable reads by guaranteeing that the database's state reflects a valid serial . In cloud storage systems, Google's Spanner exemplifies this by using its TrueTime —leveraging GPS and atomic clocks for bounded clock uncertainty—to assign globally consistent timestamps to transactions, achieving external consistency that strengthens to strict serializability for multi-key operations. Implementing strict sequential consistency in distributed systems presents significant challenges, particularly due to network latency and partitions, which can render global synchronization prohibitively expensive and lead to reduced availability under the theorem's constraints. During partitions, systems enforcing sequential consistency may halt to avoid inconsistencies, as all nodes must agree on a despite unreliable communication. To mitigate these issues, many systems adopt hybrid models that provide sequential consistency for critical reads while allowing for writes, balancing latency and without sacrificing core guarantees for high-priority operations. For example, consensus protocols like in replicated state machines offer sequential consistency-like guarantees by linearizing operations within committed logs, adapting to partitions through and log replication while tolerating temporary unavailability.

References

  1. [1]
    [PDF] How to Make a Correct Multiprocess Program Execute Correctly on ...
    sequential consistency, meaning that the program behaves as if the memory accesses of all processes were interleaved and then executed sequentially [10]. It ...
  2. [2]
    [PDF] Memory Consistency Models - Computer Science
    Sequential consistency guarantees that the result of any execution of n processors is the same as if the opera- tions of all processors were executed in some ...Missing: survey | Show results with:survey
  3. [3]
    [PDF] Shared Memory Consistency Models
    Sequential Consistency(Lamport) “A multiprocessor is sequentially consistent if the result of any execution is the same as if the operations of all the ...
  4. [4]
    [PDF] Synchronization and Sequential Consistency
    Nov 7, 2005 · Leslie Lamport. Sequential Consistency = arbitrary order-preserving interleaving of memory references of sequential programs. November 7, 2005 ...
  5. [5]
    [PDF] Shared Memory Consistency Models: A Tutorial
    To see how the use of write buffers can violate sequential consistency, consider the program in Figure 5(a). The program depicts Dekker's algorithm also shown ...
  6. [6]
    The History of the Development of Parallel Computing
    [174] Sequent produces its first shared-memory Balance multiprocessors, using NS32016 microprocessors and a proprietary Unix-like symmetric operating system ...Missing: rise | Show results with:rise
  7. [7]
    How to Make a Multiprocessor Computer That Correctly Executes ...
    Abstract: Many large sequential computers execute operations in a different order than is specified by the program. A correct execution is achieved if the ...Missing: consistency | Show results with:consistency
  8. [8]
    [PDF] Shared Memory Consistency Models: A Tutorial - Computer
    The memory consistency model of a shared memory multiprocessor for- mally specifies how the memory system will appear to the programmer. Essentially, a memory ...
  9. [9]
    [PDF] On the Definition of Sequential Consistency
    Oct 17, 2004 · it was proposed as an operational model for sequential consistency. ... According to the semantics given in [3], the two computations are ...
  10. [10]
    [PDF] Part 1. Axiomatic Sequential Consistency - Inria
    A transcription of L. Lamport's definition. Definition (SC 1). An execution is SC when there exists a total strict order on events < ...
  11. [11]
    [PDF] A Unified Formalization of Four Shared-Memory Models
    This paper presents a shared-memory model, data-race-free-1, that unifies four earlier models: weak order- ing, release consistency (with sequentially ...
  12. [12]
    Memory models: a case for rethinking parallel languages and ...
    Adve, S.V. and Gharachorloo, K. Shared memory consistency models: A tutorial. IEEE Computer 29, 12 (1996), 66--76. Digital Library · Google Scholar. [3]. Adve ...
  13. [13]
    [PDF] Linearizability: A Correctness Condition for Concurrent Objects
    Lamport's notion of sequential consistency [31] requires that a history be equiv- alent to a legal sequential history. Sequential consistency is weaker than ...
  14. [14]
    [PDF] Sequential Consistency & TSO - UPenn CIS
    • The most intuitive MC model is sequential consistency. • First formalized ... the operations of all cores were executed in some sequential order, and the ...
  15. [15]
    [PDF] A Better x86 Memory Model: x86-TSO - University of Cambridge
    This is broadly similar to the SPARC Total Store Ordering. (TSO) memory model [20,21], which is essentially an axiomatic description of the behaviour of write- ...
  16. [16]
    [PDF] Model Checking of C++ Programs under the x86-TSO Memory Model?
    “TSO bugs” shows the number of errors caused by relaxed memory in bench- marks which were not supposed to contain any bugs under sequential consistency. All ...
  17. [17]
    [PDF] Memory Consistency Models for Shared-Memory Multiprocessors ...
    From Dekker's Algorithm: P1. P2. A = 1. (a). B = 1 (c) x = B (b) y = A (d) ... • Sequential consistency disallows reordering of shared accesses. • What ...
  18. [18]
    Concurrent Programming - University of Iowa
    This was first realized by T. J. Dekker and published (by Dijkstra) in 1965. Dekker's algorithm uses busy waiting and works for only two processes. The basic ...
  19. [19]
    [PDF] Implementing Fault-Tolerant Services Using the State Machine ...
    This paper reviews the approach and describes protocols for two different failure models-Byzantine and fail stop. System reconfiguration techniques for removing ...
  20. [20]
    [PDF] In Search of an Understandable Consensus Algorithm
    May 20, 2014 · Strong leader: Raft uses a stronger form of leader- ship than other consensus algorithms. For example, log entries only flow from the leader to ...
  21. [21]
    Implementing fault-tolerant services using the state machine approach
    The state machine approach is a general method for implementing fault-tolerant services in distributed systems. This paper reviews the approach.
  22. [22]
    Consistency Models - Jepsen
    For single-object models, strict serializable implies linearizable, which implies sequential, which implies causal. Causal implies writes follow reads and PRAM.
  23. [23]
    [PDF] Spanner: Google's Globally-Distributed Database
    This paper describes how Spanner is structured, its feature set, the rationale underlying various design decisions, and a novel time API that exposes clock ...
  24. [24]
    [PDF] Consistency models in distributed systems - arXiv
    Feb 8, 2019 · Some other mentioned models such as the sequential and causal consistencies are the two models that have presented the hybrid consistency.