[go: nahoru, domu]

Jump to content

Thread safety: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
No edit summary
Mmernex (talk | contribs)
m Change from unref to no-footnotes
Line 1: Line 1:
{{unreferenced|date=June 2009}}
{{no footnotes|date=June 2009}}
'''Thread safety''' is a [[computer programming]] concept applicable in the context of [[Thread (computer science)|multi-threaded]] programs. A piece of code is '''thread-safe''' if it can be used in a multi-threaded environment.
'''Thread safety''' is a [[computer programming]] concept applicable in the context of [[Thread (computer science)|multi-threaded]] programs. A piece of code is '''thread-safe''' if it can be used in a multi-threaded environment.



Revision as of 13:26, 15 December 2010

Thread safety is a computer programming concept applicable in the context of multi-threaded programs. A piece of code is thread-safe if it can be used in a multi-threaded environment.

Thread safety is a key challenge in multi-threaded programming. It was not a concern of most application programmers for little home applications, but since the 1990s, as Windows become multithreading, and the expansion of BSD and Linux operating systems, has become a commonplace issue. In a multi-threaded program, several threads execute simultaneously in a shared address space. Every thread has access to virtually all the memory of every other thread. Thus the flow of control and the sequence of accesses to data often have little relation to what would be reasonably expected by looking at the text of the program, violating the principle of least astonishment. Thread safety is a property that allows code to run in multi-threaded environments by re-establishing some of the correspondences between the actual flow of control and the text of the program, by means of Process syncronization

Identification

It is not easy to determine if a piece of code is thread-safe or not. However, there are several indicators that suggest the need for careful examination to see if it is unsafe:

A subroutine can be reentrant, and still not thread safe. For example, a routine to open a configuration file for reading, could be reentrant (not using any globar or static variable, and using only data passed as arguments) and still, if another thread writes to the file, race conditions and strange behavior may arise.

Implementation

There are a few ways to achieve thread safety:

Re-entrancy
Writing code in such a way that it can be partially executed by one task, reentered by another task, and then resumed from the original task. This requires the saving of state information in variables local to each task, usually on its stack, instead of in static or global variables. There are still some rare cases where a static variable can be used in a reentrant function, if the access is done through atomic operations.
Mutual exclusion or Process syncronization
Access to shared data is serialized using mechanisms that ensure only one thread reads or writes the shared data at any time. Great care is required if a piece of code accesses multiple shared pieces of data—problems include race conditions, deadlocks, livelocks and starvation
Thread-local storage
Variables are localized so that each thread has its own private copy. These variables retain their values across subroutine and other code boundaries, and are thread-safe since they are local to each thread, even though the code which accesses them might be reentrant.
Atomic operations
Shared data are 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 are always kept in a valid state, no matter what other threads access it. Atomic operations form the basis of many thread locking mechanisms.

Examples

In the following piece of C code, the function is thread-safe, but not reentrant

int function()
{
	mutex_lock();
	...
	function body
	...
	mutex_unlock();
}


In the above, function can be called by different threads without any problem. But if the function is used in a reentrant interrup handler and a second interrupt arraises inside the function, the second routine will hang forver. As interrupt servicing can disable other interrups, the whole system could suffer.

In the following piece of C code, the function is reentrant, but not thread-safe

int function()
{
char *filename="/etc/config";
FILE *config;

	if(file_exist(filename)){
		config=fopen(filename);
	}
}

In the above, the function is perfectly reentrant, as it can be called any number of times and will not fail. But all the calls should be inside a single thread, where no file deletion or modification is done, in a controlled environment. If excecuted in a multi-thread environment, there is no waranty of what could another thread do to the configuration file.

Difficulties

One approach to making data thread-safe that combines several of the above elements is to make changes atomically to update the shared data. Thus, most of the code is concurrent, and little time is spent serialized.

See also