[ Team LiB ] |
2.10 Synchronizing Resource Access Across Processes on Windows2.10.1 ProblemYou want to ensure that two processes cannot simultaneously access the same resource. 2.10.2 SolutionUse a named mutex (mutually exclusive lock) to synchronize access to the resource. 2.10.3 DiscussionCoordinating access to a shared resource between multiple processes on Windows is much simpler and much more elegant than it is on Unix. For maximum portability on Unix, you must use a lock file and make sure to avoid a number of possible race conditions to make lock files work properly. On Windows, however, the use of named mutexes solves all the problems Unix has without introducing new ones. A named mutex is a synchronization object that works by allowing only a single thread to acquire a lock at any given time. Mutexes can also exist without a name, in which case they are considered anonymous. Access to an anonymous mutex can only be obtained by somehow acquiring a handle to the object from the thread that created it. Anonymous mutexes are of no use to us in this recipe, so we won't discuss them further. Mutexes have a namespace much like that of a filesystem. The mutex namespace is separate from namespaces used by all other objects. If two or more applications agree on a name for a mutex, access to the mutex can always be obtained to use it for synchronizing access to a shared resource. A mutex is created with a call to the CreateMutex( ) function. You will find it particularly useful in this recipe that the mutex is created and a handle returned, or, if the mutex already exists, a handle to the existing mutex is returned. Once we have a handle to the mutex that will be used for synchronization, using it is a simple matter of waiting for the mutex to enter the signaled state. When it does, we obtain the lock, and other processes wait for us to release it. When we are finished using the resource, we simply release the lock, which places the mutex into the signaled state. If our program terminates abnormally while it holds the lock on the resource, the lock is released, and the return from WaitForSingleObject( ) in the next process to obtain the lock is WAIT_ABANDONED. We do not check for this condition in our code because the code is intended to be used in such a way that abandoning the lock will not have any adverse effects. This is essentially the same type of behavior as that in the Unix lock file code from Recipe 2.9, where it attempts to break the lock if the process holding it terminates unexpectedly. To obtain a lock, call SpcLockResource( ) with the name of the lock. If the lock is successfully obtained, the return will be a handle to the lock; otherwise, the return will be NULL, and GetLastError( ) can be used to determine what went wrong. When you're done with the lock, release it by calling SpcUnlockResource( ) with the handle returned by SpcLockResource( ). #include <windows.h> HANDLE SpcLockResource(LPCTSTR lpName) { HANDLE hResourceLock; if (!lpName) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } if (!(hResourceLock = CreateMutex(0, FALSE, lpName))) return 0; if (WaitForSingleObject(hResourceLock, INFINITE) = = WAIT_FAILED) { CloseHandle(hResourceLock); return 0; } return hResourceLock; } BOOL SpcUnlockResource(HANDLE hResourceLock) { if (!ReleaseMutex(hResourceLock)) return FALSE; CloseHandle(hResourceLock); return TRUE; } 2.10.4 See Also |
[ Team LiB ] |