Race condition: Difference between revisions

no edit summary
(Added lock solution)
No edit summary
Line 1:
A '''race condition''' isdescribes a conditionclass whereof programming, design or implementation bug in which the outcome of ansome instructionprocess dependsor function call can vary depending on interferencethe sheduling/processing of fromother another [[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.
 
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.
 
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.
 
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==
Line 39 ⟶ 49:
 
In the above code, we lock our object before we attempt to do anything with it. Mind you, in this example, we ''don't'' know how Lock() is implemented; Implementations vary between languages, support libraries and operating systems. However, we're assured that no other (appropriately-behaving) thread will be able to make a change to our object while we're working with it. If another thread has a lock when we call Lock(), ''our thread will hang'' until that other thread releases the lock. Once the other thread releases the lock, our thread will continue.
 
Various sorts of locking primitives include [[semaphore]]s and [[mutex]]es (mutual exclusion objects).
 
{{stub}}
Anonymous user