ABA problem

ABA problem

In multithreaded computing, the ABA problem occurs during synchronization, when a location is read twice, has the same value for both reads, and "value is the same" is used to indicate "nothing has changed". However, another thread can execute between the two reads and change the value, do other work, then change the value back, thus fooling the first thread in to thinking "nothing has changed" even though the second thread did work that violates that assumption.

The ABA problem occurs when multiple threads (or processes) accessing shared memory interleave. Below is the sequence of events that will result in the ABA problem:
* Process P_1 reads value A from shared memory,
* P_1 is preempted, allowing process P_2,
* P_2 modifies the shared memory value A to value B and back to A before preemption,
* P_1 begins execution again, sees that the shared memory value has not changed and continues.

Although P_1 can continue executing, it is possible that the behavior will not be correct due to the "hidden" modification in shared memory.

A common case of the ABA problem is encountered when implemening a lock-free data structure. If an item is removed from the list, deleted, and then a new item is allocated and added to the list, it is common for the allocated object to be at the same location as the deleted object thanks to optimizations in the memory manager. A pointer to the new item is thus sometimes equal to a pointer to the old item which is an ABA problem.

Example

Consider this lock-free stack:

/* Naive lock-free stack which suffers from ABA problem.*/ class Stack { volatile Obj* top_ptr; // // Pops the top object and returns a pointer to it. // Obj* Pop() { while(1) { Obj* ret_ptr = top_ptr; if (!ret_ptr) return NULL; Obj* next_ptr = ret_ptr->next; // If the top node is still ret, then assume no one has changed the stack. // (That statement is not always true because of the ABA problem) // Atomically replace top with next. if (CompareAndExchange(top_ptr, ret_ptr, next_ptr)) { return ret_ptr; } // The stack has changed, start over. } } // // Pushes the object specified by obj_ptr to stack. // void Push(Obj* obj_ptr) { while(1) { Obj* next_ptr = top_ptr; obj->next = next_ptr; // If the top node is still next, then assume no one has changed the stack. // (That statement is not always true because of the ABA problem) // Atomically replace top with obj. if (CompareAndExchange(top_ptr, next_ptr, obj_ptr)) { return; } // The stack has changed, start over. } }

This code can normally prevent problems from concurrent access, but suffers from ABA problems. Consider the following sequence:

Stack initially contains top -> A -> B -> C

Thread 1 starts running pop: ret = A; next = B;Thread 1 gets interrupted just before the CompareExchange...

{ // Thread 2 runs pop: ret = A; next = B; CompareExchange(A, A, B) // Success, top = B return A; } // Now the stack is top -> B -> C { // Thread 2 runs pop again: ret = B; next = C; CompareExchange(B, B, C) // Success, top = C return B; } // Now the stack is top -> C delete B; { // Thread 2 now pushes A back onto the stack: A->next = C; CompareExchange(C, C, A) // Success, top = A }

Now the stack is top -> A -> C

When Thread 1 resumes: CompareExchange(A, A, B)

This instruction succeeds because it finds top = ret (both are A), so it sets top to next (which is B). But B was deleted! Bad things will result...

Workarounds

A common workaround is to add extra "tag" bits to the quantity being considered. For example, an algorithm using compare and swap on a pointer might use the low bits of the address to indicate how many times the pointer has been successfully modified. Because of this, the next compare-and-swap will fail, even if the addresses are the same, because the tag bits will not match. This does not completely solve the problem, as the tag bits will eventually wrap around, but helps to avoid it. Some architectures provide a double-word compare and swap, which allows for a larger tag. This is sometimes called ABA' since the second A is made slightly different from the first.

A correct but expensive approach is to use intermediate nodes that are not data elements and thus assure invariants as elements are inserted and removed [Valois] .

Another approach is to use one or more hazard pointers, which are pointers to locations that otherwise cannot appear in the list. Each hazard pointer represents an intermediate state of an in-progress change; the presence of the pointer assures further synchronization [Doug Lea] .

Some architectures provide "larger" atomic operations such that, as example, both forward and backward links in a doubly-linked list can be updated atomically.

Some architectures provide a load linked, store conditional instruction in which the store is performed only when there are no other stores of the indicated location. This effectively separates the notion of "storage contains value" from "storage has been changed". Examples include DEC Alpha and PowerPC.

References

# Damian Dechev, Peter Pirkelbauer, and Bjarne Stroustrup. [http://www.research.att.com/~bs/lock-free-vector.pdf Lock-free Dynamically Resizable Arrays]


Wikimedia Foundation. 2010.

Игры ⚽ Нужно сделать НИР?

Look at other dictionaries:

  • ABA — may refer to:* American Bar Association * AB Aerotransport, a former Scandinavian airline * IATA airport code for Abakan Airport, in Russia * Académie des Beaux Arts (Kinshasa) * Aberdare railway station, in the United Kingdom * Abscisic Acid, a… …   Wikipedia

  • Aba CM Enablement — is an engineering data management, configuration management and change control tool that allows users connected only by a TCP/IP network to share and control data. Most CM tools only control a small part of a project s configuration; Aba makes it …   Wikipedia

  • ABA-Liga — ABA League Sportart Basketball Gründungsjahr 2001 Mannschaften 14 Teams …   Deutsch Wikipedia

  • ABA–NBA merger — The ABA–NBA merger was the merger of the American Basketball Association with the National Basketball Association, which after multiple attempts over several years finally occurred in 1976. Contents 1 Origins of ABA NBA competition 2 Early… …   Wikipedia

  • Unentscheidbares Problem — Eine Eigenschaft auf einer Menge heißt entscheidbar (auch: rekursiv), wenn es ein Entscheidungsverfahren für sie gibt. Ein Entscheidungsverfahren ist ein Algorithmus, der für jedes Element der Menge beantworten kann, ob es die Eigenschaft hat… …   Deutsch Wikipedia

  • Napoleon's problem — is a famous compass construction problem. In it, a circle and its center are given. The challenge is to divide the circle into four equal arcs using only a compass. Napoleon was known to be an amateur mathematician but it is not known if he… …   Wikipedia

  • Compare-and-swap — In computer science, the compare and swap (CAS) CPU instruction is a special instruction that atomically compares the contents of a memory location to a given value and, only if they are the same, modifies the contents of that memory location to… …   Wikipedia

  • Non-blocking algorithm — In computer science, a non blocking algorithm ensures that threads competing for a shared resource do not have their execution indefinitely postponed by mutual exclusion. A non blocking algorithm is lock free if there is guaranteed system wide… …   Wikipedia

  • Lock-free and wait-free algorithms — In contrast to algorithms that protect access to shared data with locks, lock free and wait free algorithms are specially designed to allow multiple threads to read and write shared data concurrently without corrupting it. Lock free refers to the …   Wikipedia

  • Adria-Liga — ABA League Sportart Basketball Gründungsjahr 2001 Mannschaften 14 Teams …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”