Thread-safety
   HOME

TheInfoList



OR:

Thread safety is a computer programming concept applicable to multi-threaded code. Thread-safe code only manipulates shared data structures in a manner that ensures that all threads behave properly and fulfill their design specifications without unintended interaction. There are various strategies for making thread-safe data structures. A program may execute code in several threads simultaneously in a shared
address space In computing, an address space defines a range of discrete addresses, each of which may correspond to a network host, peripheral device, disk sector, a memory cell or other logical or physical entity. For software programs to save and retrieve st ...
where each of those threads has access to virtually all of the memory of every other thread. Thread safety is a property that allows code to run in multithreaded environments by re-establishing some of the correspondences between the actual flow of control and the text of the program, by means of
synchronization Synchronization is the coordination of events to operate a system in unison. For example, the conductor of an orchestra keeps the orchestra synchronized or ''in time''. Systems that operate with all parts in synchrony are said to be synchronou ...
.


Levels of thread safety

Software libraries In computer science, a library is a collection of non-volatile resources used by computer programs, often for software development. These may include configuration data, documentation, help data, message templates, pre-written code and subro ...
can provide certain thread-safety guarantees. For example, concurrent reads might be guaranteed to be thread-safe, but concurrent writes might not be. Whether a program using such a library is thread-safe depends on whether it uses the library in a manner consistent with those guarantees. Different vendors use slightly different terminology for thread-safety: *Thread safe: Implementation is guaranteed to be free of race conditions when accessed by multiple threads simultaneously. *Conditionally safe: Different threads can access different objects simultaneously, and access to shared data is protected from race conditions. *Not thread safe: Data structures should not be accessed simultaneously by different threads. Thread safety guarantees usually also include design steps to prevent or limit the risk of different forms of deadlocks, as well as optimizations to maximize concurrent performance. However, deadlock-free guarantees cannot always be given, since deadlocks can be caused by
callbacks In computer programming, a callback or callback function is any reference to executable code that is passed as an argument to another piece of code; that code is expected to ''call back'' (execute) the callback function as part of its job. Thi ...
and violation of
architectural layer In computing, an abstraction layer or abstraction level is a way of hiding the working details of a subsystem. Examples of software models that use layers of abstraction include the OSI model for network protocols, OpenGL, and other graphics libra ...
ing independent of the library itself.


Implementation approaches

Below we discuss two classes of approaches for avoiding race conditions to achieve thread-safety. The first class of approaches focuses on avoiding shared state and includes: ; Re-entrancy: Writing code in such a way that it can be partially executed by a thread, executed by the same thread, or simultaneously executed by another thread and still correctly complete the original execution. This requires the saving of state information in variables local to each execution, usually on a stack, instead of in static or global variables or other non-local state. All non-local states must be accessed through atomic operations and the data-structures must also be reentrant. ;
Thread-local storage Thread-local storage (TLS) is a computer programming method that uses static or global memory local to a thread. While the use of global variables is generally discouraged in modern programming, legacy operating systems such as UNIX are designed ...
: Variables are localized so that each thread has its own private copy. These variables retain their values across
subroutine In computer programming, a function or subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed. Functions may ...
and other code boundaries and are thread-safe since they are local to each thread, even though the code which accesses them might be executed simultaneously by another thread. ;
Immutable object In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created.Goetz et al. ''Java Concurrency in Practice''. Addison Wesley Professional, 2006, Section 3.4 ...
s: The state of an object cannot be changed after construction. This implies both that only read-only data is shared and that inherent thread safety is attained. Mutable (non-const) operations can then be implemented in such a way that they create new objects instead of modifying existing ones. This approach is characteristic of functional programming and is also used by the ''string'' implementations in Java, C#, and Python. (See
Immutable object In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created.Goetz et al. ''Java Concurrency in Practice''. Addison Wesley Professional, 2006, Section 3.4 ...
.) The second class of approaches are synchronization-related, and are used in situations where shared state cannot be avoided: ; Mutual exclusion: Access to shared data is ''serialized'' using mechanisms that ensure only one thread reads or writes to the shared data at any time. Incorporation of mutual exclusion needs to be well thought out, since improper usage can lead to side-effects like deadlocks,
livelock In concurrent computing, deadlock is any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action, such as sending a message or, more commonly, releasing a loc ...
s, and
resource starvation In computer science, resource starvation is a problem encountered in concurrent computing where a process is perpetually denied necessary resources to process its work. Starvation may be caused by errors in a scheduling or mutual exclusion algori ...
. ;
Atomic operations In concurrent programming, an operation (or set of operations) is linearizable if it consists of an ordered list of invocation and response events (event), that may be extended by adding response events such that: # The extended list can be re-e ...
: Shared data is accessed by using atomic operations which cannot be interrupted by other threads. This usually requires using special machine language instructions, which might be available in a runtime library. Since the operations are atomic, the shared data is always kept in a valid state, no matter how other threads access it. Atomic operations form the basis of many thread locking mechanisms, and are used to implement mutual exclusion primitives.


Examples

In the following piece of Java code, the Java keyword synchronized makes the method thread-safe: class Counter In the
C programming language ''The C Programming Language'' (sometimes termed ''K&R'', after its authors' initials) is a computer programming book written by Brian Kernighan and Dennis Ritchie, the latter of whom originally designed and implemented the language, as well as ...
, each thread has its own stack. However, a static variable is not kept on the stack; all threads share simultaneous access to it. If multiple threads overlap while running the same function, it is possible that a static variable might be changed by one thread while another is midway through checking it. This difficult-to-diagnose logic error, which may compile and run properly most of the time, is called a race condition. One common way to avoid this is to use another shared variable as a "lock" or "mutex" (from mutual exclusion). In the following piece of C code, the function is thread-safe, but not reentrant: # include int increment_counter () In the above, increment_counter can be called by different threads without any problem since a mutex is used to synchronize all access to the shared counter variable. But if the function is used in a reentrant interrupt handler and a second interrupt arises while the mutex is locked, the second routine will hang forever. As interrupt servicing can disable other interrupts, the whole system could suffer. The same function can be implemented to be both thread-safe and reentrant using the lock-free atomics in C++11: # include int increment_counter ()


See also

* Concurrency control * Exception safety * Priority inversion *
ThreadSafe ThreadSafe is a source code analysis tool that identifies application risks and security vulnerabilities associated with concurrency in Java code bases, using whole-program interprocedural analysis. ThreadSafe is used to identify and avoid softw ...


References


External links

* * * *{{cite web, url=http://www.thinkingparallel.com/2006/10/15/a-short-guide-to-mastering-thread-safety/, title=A Short Guide to Mastering Thread-Safety, last=Suess, first=Michael, date=15 October 2006, website=Thinking Parallel, access-date=2012-01-22 Threads (computing) Programming language topics