Important points about Synchronization Technique
1. Critical Section
1. Critical section object provides synchronization to a single process.2. Event, Mutex and Semaphore can also be used in a single process application.
3. Critical section objects provide a slightly faster, more efficient mechanism for synchronization.
4. Like Mutex, Critical Section object can be owned by only one thread at a time.
5. Unlike a Mutex object, there is no way to tell whether a critical section has been abandoned.
6. Threads waiting on a critical section do not acquire the critical section on first-come, first-serve basis.
7. Windows Server 2003 and Windows XP: Threads that are waiting on a critical section are added to a wait queue, they are woken up generally acquire the critical section in the order in which they are added in the queue.
8. If a thread terminates while it has ownership of a critical section, the state of the critical section is undefined.
9. If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.
InitializeCriticalSection:
1. Initialize a critical section object.2. In low memory situation, this method can raise an exception.
3. Before using a critical section, some thread of the process must initialize the object.
4. A critical section object must be deleted before it can be reinitialized.
5. Initializing a critical section that has already been initialized results in undefined behaviour.
ex:
CRITICAL_SECTION BufferLock;
InitializeCriticalSection (&BufferLock);
EnterCriticalSection:
1. Wait for ownership of the specified critical section object.2. The function returns when the calling thread is granted ownership.
3. This function can raise an exception ("EXCEPTION_POSSIBLE_DEADLOCK"), if a wait operation on the critical section times out.
4. The timeout interval specified by the following registry value:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout.
5. To enable mutually exclusive access to a shared resource, each thread calls the EnterCriticalSection function to request ownership of the critical section before executing any section of code that accesses the protected resource.
6. After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns.
ex:
CRITICAL_SECTION BufferLock;
InitializeCriticalSection (&BufferLock);
EnterCriticalSection (&BufferLock);
LeaveCriticalSection:
1. Release ownership of the specified critical section object.2. If a thread calls LeaveCriticalSection when it does not have ownership of the specified critical section object, an error occurs that may cause another thread using EnterCriticalSection to wait indefinitely.
ex:
CRITICAL_SECTION BufferLock;
InitializeCriticalSection (&BufferLock);
EnterCriticalSection (&BufferLock);
LeaveCriticalSection (&BufferLock);
DeleteCriticalSection:
1. Release all resources used by an unowned critical section object.2. If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.
2. Condition Variables:
1. Condition variables are synchronization primitives that enable threads to wait until a particular condition occurs.
2. Condition variables are user-mode objects that cannot be shared across processes.
3. Condition variables enable threads to atomically release a lock and enter the sleeping state
4. They can be used with critical sections or slim reader/writer (SRW) locks.
5. After a thread is woken, it re-acquires the lock it released when the thread entered the sleeping state.
ex:
CONDITION_VARIABLE BufferNotEmpty;
InitializeConditionVariable:
1. Initialize a condition Variable
ex:
CONDITION_VARIABLE BufferNotEmpty;
InitializeConditionVariable (&BufferNotEmpty);
SleepConditionVariableCS: (For CriticalSection lock)
1. Sleeps on specified condition variable and releases the specified critical section as an atomic operation.
2. If the time-out interval elapses, the function re-acquires the critical section and returns zero.
3. If timeout is zero, the function tests the states of the specified objects and returns immediately.
4. If timeout is INFINITE, the function's time-out interval never elapses.
ex:
CONDITION_VARIABLE BufferNotFull;
CRITICAL_SECTION BufferLock;
SleepConditionVariableCS (&BufferNotFull, &BufferLock, INFINITE);
SleepConditionVariableSRW: (For slim reader/writer lock)
1. Sleeps on the specified condition variable and releases the specified lock as an atomic operation.
2. If the lock is unlocked when this function is called, the function behavior is undefined.
3. If the function succeeds, the return value is nonzero.
4. If the function fails, the return value is zero. To get extended error information, call GetLastError.
5. If the timeout expires the function returns FALSE and GetLastError returns ERROR_TIMEOUT.
WakeConditionVariable:
1. Wake a single thread waiting on the specified condition variable.
ex:
CONDITION_VARIABLE BufferNotFull;
WakeConditionVariable (&BufferNotFull);
WakeAllConditionVariable:
1. Wake all threads waiting on the specified condition variable.
ex:
CONDITION_VARIABLE BufferNotFull;
WakeAllConditionVariable (&BufferNotFull);
3.Mutex
1. Mutex object is a synchronisation object useful in coordinating mutually exclusive access to a shred resources.
2. Its state is set to signaled when it is not owned by any thread, and nonsignled when it is owned.
3. For example, to prevent two threads from writing to shared memory at the same time, each thread waits for ownership of a mutex object before executing the code that accesses the memory. After writing to the shared memory, the thread releases the mutex object.
4. The state of a mutex object is signaled when it is not owned by any thread
5. The creating thread can use the bInitialOwner flag to request immediate ownership of the mutex. Otherwise, a thread must use one of the wait functions to request ownership.
6. When the mutex's state is signaled, one waiting thread is granted ownership, the mutex's state changes to nonsignaled, and the wait function returns.
7. Only one thread can own a mutex at any given time.
8. The thread that owns a mutex can specify the same mutex in repeated wait function calls without blocking its execution. Typically, you would not wait repeatedly for the same mutex, but this mechanism prevents a thread from deadlocking itself while waiting for a mutex that it already owns.
9.The following object-sharing mechanisms are available:
1. A child process created by the CreateProcess function can inherit a handle to a mutex object if the lpMutexAttributes parameter of CreateMutex enabled inheritance. This mechanism works for both named and unnamed mutexes.
2. A process can specify the handle to a mutex object in a call to the DuplicateHandle function to create a duplicate handle that can be used by another process.This mechanism works for both named and unnamed mutexes.
3. A process can specify a named mutex in a call to the OpenMutex or CreateMutex function to retrieve a handle to the mutex object.
10. If your multithreaded application must repeatedly create, open, and close a named mutex object, a race condition can occur. In this situation, it is better to use CreateMutex instead of OpenMutex, because CreateMutex opens a mutex if it exists and creates it if it does not.
CreateMutex:
1. Creates or opens a named or unnamed mutex object.
2. If given mutex name matches the name of an existing event, semaphore, waitable timer, job or file-mapping object, this function fails and "GetLastError" function returns ERROR_INVALID_HANDLE.
3. This occurs, because these objects share the same namespace.
HANDLE WINAPI CreateMutex(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
_In_ BOOL bInitialOwner,
_In_opt_ LPCTSTR lpName
);
4. if lpMutexAttributes is NULL, the handle can not be inherited by child process.
5. bInitialOwner : If the value is TRUE and the caller creates the mutex, the calling thread obtains initial ownership.
6. If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object. GetLastError returns ERROR_ALREADY_EXISTS, and the calling thread is not granted ownership.
OpenMutex
1. Opens an existing named mutex object
2. The OpenMutex function enables multiple processes to open handles of the same mutex object.
3. The function succeeds only if some process has already created the mutex by using the CreateMutex function.
HANDLE WINAPI OpenMutex(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCTSTR lpName
);
4. dwDesiredAccess: Only the SYNCHRONIZE access right is required to use a mutex
5. bInheritHandle: If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
6. lpName: The name of the mutex to be opened. Name comparisons are case sensitive.
7. Return Value:
If the function succeeds, the return value is a handle to the mutex object.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
If a named mutex does not exist, the function fails and GetLastError returns ERROR_FILE_NOT_FOUND.
ReleaseMutex:
1. Releases ownership of the specified mutex object.
2. The ReleaseMutex function fails if the calling thread does not own the mutex object.
3. When the thread no longer needs to own the mutex object, it calls the ReleaseMutex function so that another thread can acquire ownership.
BOOL WINAPI ReleaseMutex(
_In_ HANDLE hMutex
);
CloseHandle:
1. Closes an open object handle.
2. CloseHandle invalidates the specified object handle, decrements the object's handle count, and performs object retention checks.
3. After the last handle to an object is closed, the object is removed from the system.
BOOL WINAPI CloseHandle(
_In_ HANDLE hObject
);
4. Semaphore
1. This is the counting based synchronization object2. It maintains count between zero and specified maximum value.
3. The count is decremented each time a thread completes a wait for the semaphore object and incremented each time a thread releases the semaphore.
4. The state of a semaphore is set to signaled when count is greater than zero and nonSignaled when count is zero.
5. Each time one of the wait functions returns because the state of a semaphore was set to signaled, the count of the semaphore is decreased by one. The ReleaseSemaphore function increases a semaphore's count by a specified amount.
6. A thread that owns a mutex object can wait repeatedly for the same mutex object to become signaled without its execution becoming blocked. A thread that waits repeatedly for the same semaphore object, however, decrements the semaphore's count each time a wait operation is completed; the thread is blocked when the count gets to zero.
7. Only the thread that owns a mutex can successfully call the ReleaseMutex function, though any thread can use ReleaseSemaphore to increase the count of a semaphore object.
8. A thread can decrement a semaphore's count more than once by repeatedly specifying the same semaphore object in calls to any of the wait functions. However, calling one of the multiple-object wait functions with an array that contains multiple handles of the same semaphore does not result in multiple decrements.
9. It limits the number of threads sharing the resource to a specified maximum number.
10. The count can never be less than zero or greater than the maximum value.
For more understanding, look at the below given example:
An application might place a limit on the number of windows that it creates. It uses a semaphore with a maximum count equal to the window limit, decreamenting the count whenever a window is created and increamenting it whenever a window is closed. The application specifies the semaphore object in call to one of the wait functions before each window is created. When the count is zero—indicating that the window limit has been reached—the wait function blocks execution of the window-creation code.
CreateSemaphore:
1. Creates or opens a named or nonnamed semaphore object.HANDLE WINAPI CreateSemaphore(
_In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
_In_ LONG lInitialCount,
_In_ LONG lMaximumCount,
_In_opt_ LPCTSTR lpName
);
2. lpSemaphoreAttributes: If this parameter is NULL, the semaphore gets a default security descriptor. The handle cannot be inherited by child processes. A child process created by the CreateProcess function can inherit a handle to a semaphore object if the lpSemaphoreAttributes parameter of CreateSemaphore enabled inheritance.
3. lInitialCount: This value must be greater than or equal to zero and less than or equal to lMaximumCount.
The state of a semaphore is signaled when its count is greater than zero and nonsignaled when it is zero.
4. lMaximumCount: The maximum count for the semaphore object. This value must be greater than zero.
5. lpName: The name of the semaphore object. The name is limited to MAX_PATH characters. Name comparison is case sensitive.
If lpName matches the name of an existing named semaphore object, it returns handle of existing semaphore objects. In this case, the lInitialCount and lMaximumCount parameters are ignored because they have already been set by the creating process.
6. A process can specify the semaphore-object handle in a call to the DuplicateHandle function to create a duplicate handle that can be used by another process.
7. A process can specify the name of a semaphore object in a call to the OpenSemaphore or createSemaphore function.
OpenSemaphore:
1. Opens an existing named semaphore2. The OpenSemaphore function enables multiple processes to open handles of the same semaphore object.
HANDLE WINAPI OpenSemaphore(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCTSTR lpName
);
3. bInheritHandle : If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
4. lpName: The name of the semaphore to be opened. Name comparisons are case sensitive.
ReleaseSemaphore:
1. Increases the count of the specified semaphore object by a specified amountBOOL WINAPI ReleaseSemaphore(
_In_ HANDLE hSemaphore,
_In_ LONG lReleaseCount,
_Out_opt_ LPLONG lpPreviousCount
);
2. hSemaphore : A handle to the Semaphore object
3. lReleaseCount : The amount by which the semaphore object's current count is to be increased. The value must be greater than zero. If the specified amount would cause the semaphore's count to exceed the maximum count that was specified when the semaphore was created, the count is not changed and the function returns FALSE.
4. lpPreviousCount : A pointer to a variable to receive the previous count for the semaphore. This parameter can be NULL if the previous count is not required.
5. The application can create a semaphore with an initial count of zero. This sets the semaphore's state to nonsignaled and blocks all threads from accessing the protected resource. When the application finishes its initialization, it uses ReleaseSemaphore to increase the count to its maximum value, to permit normal access to the protected resource.
5. Event Object:
1. This is a synchronization object whose state can be explicitly set to signaled.There are two types of Event Object:
a. Manual Reset Event: An event object whose state remains signaled untill it is explicitly reset to nonsignaled by the ResetEvent function.
While it is signaled, waiting threads can be released.
b. Auto Rest Event: An event object whose state remains signaled untill a single waiting thread is released, at which time system automatically sets the state to nonsignaled.
2. manual-reset event object requires the use of the ResetEvent function to set the event state to nonsignaled. For Auto-reset event object, the system automatically resets the event state to nonsignaled after a single waiting thread has been released.CreateEvent:
1. Creates or Opens a named or unnamed event object.HANDLE WINAPI CreateEvent(
_In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
_In_ BOOL bManualReset,
_In_ BOOL bInitialState,
_In_opt_ LPCTSTR lpName
);
2. lpEventAttributes: If lpEventAttributes is NULL, the event gets a default security descriptor. the handle cannot be inherited by child processes.
3. bManualReset: If this parameter is TRUE, the function creates a manual-reset event object otherwise creates an Auto-reset event.
4. bInitialState: If this parameter is TRUE, the initial state of the event object is signaled; otherwise, it is nonsignaled.
5. lpName : If lpName matches the name of an existing named event object, it returns handle of existing even objects. In this case,the bManualReset and bInitialState parameters are ignored because they have already been set by the creating process.
OpenEvent:
1. Opens an existing named event object.2. The OpenEvent function enables multiple processes to open handles of the same event object.
HANDLE WINAPI OpenEvent(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCTSTR lpName
);
3. bInheritHandle : If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
4. lpName: The name of the semaphore to be opened. Name comparisons are case sensitive.
SetEvent:
1. Sets the specified event object to the signaled state.2. Setting an event that is already set has no effect.
BOOL WINAPI SetEvent(
_In_ HANDLE hEvent
);
ResetEvent:
1. Sets the specified event object to the nonsignaled state.BOOL WINAPI ResetEvent(
_In_ HANDLE hEvent
);
6. WaitFunctions
1. Wait functions allow a thread to block its own execution
2. When a wait function is called, it checks whether the wait criteria have been met
3. f the criteria have not been met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the specified time-out interval elapses.
Single-Object Wait Functions:(WaitForSingleObject, WaitForSingleObjectEx and SignalObjectAndWait)
1. These functions return when:
a The specified object is in signaled state
b. The time-out interval elapses.
c. The time-out interval can be set to INFINITE to specify that the wait will not time out.
2. The SignalObjectAndWait function enables the calling thread to atomically set the state of an object to signaled and wait for the state of another object to be set to signaled.
Multiple-object Wait Functions: (WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjects and MsgWaitForMultipleObjecsEx)
1. These functions return when:
a. The state of any one of the specified objects is set to signaled or the states of all objects have been set to signaled.
b. The time-out interval elapses.
c. The time-out interval can be set to INFINITE to specify that the wait will not time out.
2. When waiting for the states of all objects to be set to signaled, these multiple-object functions do not modify the states of the specified objects until the states of all objects have been set signaled. For example, the state of a mutex object can be signaled, but the calling thread does not get ownership until the states of the other objects specified in the array have also been set to signaled.
3.In the meantime, some other thread may get ownership of the mutex object, thereby setting its state to nonsignaled.
4. The MsgWaitForMultipleObjects and MsgWaitForMultipleObjectsEx function allow you to specify input event objects in the object handle array. This is done when you specify the type of input to wait for in the thread's input queue. For example, a thread could use MsgWaitForMultipleObjects to block its execution until the state of a specified object has been set to signaled and there is mouse input available in the thread's input queue.
Wait Functions and Synchronization Objects:
1. The Wait functions can modify the state of some of synchronization objects.
2. Modification occurs for the object/s whose signaled state caused the function to return.
3. Following can be modified:
a. The count of a semaphore object decreased by one.
b. The state of the semaphore object is set to nonsignaled if its count is zero.
c. The state of mutex, auto-reset event and change-notification objects are set to nonsignaled.
d. The state of synchronizztion timer is et to nonsignaled.
e. The state of Manual-reset event, manual-reset timer, process, thread and console input objects are not affected by a wait function.
No comments:
Post a Comment