Concurrent data structures, intended for use in parallel or distributed computing environments, differ from "sequential" data structures, intended for use on a uni-processor machine, in several ways. Most notably, in a sequential environment one specifies the data structure's properties and checks that they are implemented correctly, by providing
safety properties. In a concurrent environment, the specification must also describe
liveness properties which an implementation must provide. Safety properties usually state that something bad never happens, while liveness properties state that something good keeps happening. These properties can be expressed, for example, using
linear temporal logic. The type of liveness requirements tend to define the data structure. The
method calls can be
blocking or
non-blocking. Data structures are not restricted to one type or the other, and can allow combinations where some method calls are blocking and others are non-blocking (examples can be found in the
Java concurrency software library). The safety properties of concurrent data structures must capture their behavior given the many possible interleavings of methods called by different threads. It is quite intuitive to specify how abstract data structures behave in a sequential setting in which there are no interleavings. Therefore, many mainstream approaches for arguing the safety properties of a concurrent data structure (such as
serializability,
linearizability,
sequential consistency, and quiescent consistency) specify the structures properties sequentially, and map its concurrent executions to a collection of sequential ones. To guarantee the safety and liveness properties, concurrent data structures must typically (though not always) allow threads to reach
consensus as to the results of their simultaneous data access and modification requests. To support such agreement, concurrent data structures are implemented using special primitive synchronization operations (see
synchronization primitives) available on modern
multiprocessor machines that allow multiple threads to reach consensus. This consensus can be achieved in a blocking manner by using
locks, or without locks, in which case it is
non-blocking. There is a wide body of theory on the design of concurrent data structures (see bibliographical references). ==Design and implementation==