Race condition: Difference between revisions

Reorganized somewhat.
m (Improved link syntax)
(Reorganized somewhat.)
Line 1:
A '''race condition''' describes a class of programming, design or implementation bug in which the outcome of some process or function call can vary depending on the sheduling/processing of other [[thread]]s or [[process]]es. Commonly, this interference comes in the form of two processes depending on or manipulating the same piece of memory, or on multiple processes attemping access to the same file.
 
 
==Reasons==
 
In any situation where a resource is shared and potentially concurrently accessible there are possible race conditions. Such situations require specific contention avoidance or mitigation processes.
 
===File access===
 
For example when creating a new file on a local UNIX or Linux filesystem two processes might attempt to use the same filename at the same time. One of them will create the filesystem while the other might merely open the newly created file. Using special flags to the ''open()'' system call it's possible to guarantee that the file will be created and exclusively opened ... or that it will return an error if the file already exists. Thus the '''O_EXCL''' and the '''O_CREAT''' flags to the ''open()'' system call are required to make this guarantee. (Additionally code must check for the possible failure/error condition).
 
As a further example the O_EXCL|O_CREAT combination of flags is '''not''' sufficient for providing the same race free guaranteed on an NFS (networked) filesystem. The guarantee regarding ''open()'s'' semantics is only valid for local filesystems. Avoiding race conditions in creating files over NFS requires the use of unique temporary filenames, and the use of ''link()'' and possibly ''fstat()'' system calls. It's possible to write code which is guaranteed to be race free for both situations (under standards comformant implementations of UNIX and NFS). However it's very easy to mistakenly use one form of code over the other situation in ways that will only rarely fail.
 
===Shared memory===
 
Race considerations also apply to shared memory. [[Threads]] implicitly share most or all of their memory, and it's possible for [[process]]es to share memmory via POSIX or SysV APIs (for UNIX/Linux) or via other (operating system specific) means. On any sort of multi-processor or "hyper-threaded" hardware there can be races for memory access. However, even on single-CPU (uniprocessor) systems there can be races between fetching a value (into a CPU register) and writing a new value back out to memory. Programming languages with support for threading supply various forms of locking and synchronization primitives, and sometimes high-level APIs which must be used to co-ordinate all access to shared memory. Additionally one normally uses SysV or POSIX semaphore APIs along with the corresponding shared memory features to handle contention.
 
The concept of "race conditions" can apply to any form of shared memory or storage resource and many networking and communications domains. Each such situation imposes specific requirements on the programmer to avoid races; and generally there is no way to definitively test for race conditions. (Tests can only prove that you haven't "lost" the races in some number of attempts over some specific situations). Thus the programmer must adhere careful to domain specific standards in order to guarantee that there code is race free. (Also note that the programmer is dependent on the standards compliance of the hardware, operating system, and programming tool chain; regardless of how carefully he or she as adhered to the standards).
 
==Reasons==
 
Most popular platforms perform [[multitasking]], where multiple threads of code run on the same computer. These threads may be their own processes, or they may be part of a larger program. In addition, these threads may share the same CPU core, or there may be multiple cores (or CPUs) available.
Line 29 ⟶ 34:
==Inconsistency==
 
While it's possible that another thread with access to our objectshared resourse changed it between the times when we checkedcheck for its availability and when we attemptedattempt to use it, it's also possible that the second thread operated on the shared objectresource before or after our code, in which case DoSomethingWith()our code likely wouldn't have failed. Whether or not our code fails depends on the timing of when the two threads accessed the same object. Since timing is rarely consistent, the failure of our code (or any code subject to race conditions) can be inconsistent and difficult to trace.
 
==Solutions==
Line 59 ⟶ 64:
 
Ada provides ''protected objects'' with locking characteristics based upon the kind of access method described. A protected ''procedure'' enforces a write lock, allowing unconditional access to the object by only a single thread at a time. A protected ''entry'' enforces a write lock, allowing conditional access to the object by one thread at a time. A protected ''function'' provides a shared read lock, allowing multiple read access to the object at the same time. Many locking [http://home.att.net/~jimmaureenrogers/Shared_Resource_Design_Patterns.html patterns] can be defined using these three capabilities.
 
{{stub}}