关闭

Mutex Objects

标签: Mutex Object互斥对象同步机制
384人阅读 评论(0) 收藏 举报
分类:
Mutex Objects


A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread, and nonsignaled when it is owned. 
Only one thread at a time can own a mutex object, whose name comes from the fact that it is useful in coordinating mutually exclusive access to a shared resource.
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.


Mutex Object(互斥对象) 当没有被任何线程拥有时,将被设置成有信号。当Mutex Object 被一个线程拥有时,状态将被设置成无信号。
在同一时间只能有一个线程可以拥有Mutex Object的权利。Mutex Obejct 名字来自当多个线程互相合作互斥执行访问共享对象。
例如:为了阻止两个线程在同一时间写入共享内存时,每一个线程都必须首先等待拥有Mutex Object的权利后才能继续访问内存,当写入共享内存后,线程将释放拥有Mutex Object的权利。Mutex




A thread uses the CreateMutex or CreateMutexEx function to create a mutex object.
The creating thread can request immediate ownership of the mutex object and can also specify a name for the mutex object.
It can also create an unnamed mutex. 


一个线程可以通过CreateMutex()函数和CreateMutexEx()函数来创建一个Mutex Object(互斥对象).
创建Mutex Object的线程可以立刻拥有Mutex Object的权利,同时为Mutex Object指定一个名称。也可以创建一个没有名称的Mutex Object.
Threads in other processes can open a handle to an existing named mutex object by specifying its name in a call to the OpenMutex function. 
To pass a handle to an unnamed mutex to another process, use the DuplicateHandle function or parent-child handle inheritance.


在其他进程中的线程可以通过调用OpenMutex()函数获取一个存在名称的Mutex Object.




Any thread with a handle to a mutex object can use one of the wait functions to request ownership of the mutex object. 
If the mutex object is owned by another thread, the wait function blocks the requesting thread until the owning thread releases the mutex object using the ReleaseMutex function.
The return value of the wait function indicates whether the function returned for some reason other than the state of the mutex being set to signaled.
任何线程都可以等待获取Mutex Object的权利,如果一个Mutex Object对象被一个线程拥有,那么只有该线程通过ReleaseMutex()方法释放拥有权利后,在等待的线程才能拥有该Mutex Object对象的权利。
wait 函数返回值表示Mutex Object被设置成有信号的原因。


If more than one thread is waiting on a mutex, a waiting thread is selected. Do not assume a first-in, first-out (FIFO) order. 
External events such as kernel-mode APCs can change the wait order.
如果多个线程等待拥有Mutex Object的权利,一个线程会被随机选择,而不是按照先进先出原则.但是可以通过内核API来改变等待的顺序。


After a thread obtains ownership of a mutex, it can specify the same mutex in repeated calls to the wait-functions without blocking its execution. 
This prevents a thread from deadlocking itself while waiting for a mutex that it already owns. 
To release its ownership under such circumstances, the thread must call ReleaseMutex once for each time that the mutex satisfied the conditions of a wait function.


当一个线程获取到Mutex Object的权利后,当该线程重发调用wait函数时会立刻执行而不发生阻塞。
这样就可以防止线程发生自锁现象。
If a thread terminates without releasing its ownership of a mutex object, the mutex object is considered to be abandoned. 
A waiting thread can acquire ownership of an abandoned mutex object, but the wait function will return WAIT_ABANDONED to indicate that the mutex object is abandoned. 
An abandoned mutex object indicates that an error has occurred and that any shared resource being protected by the mutex object is in an undefined state. 
If the thread proceeds as though the mutex object had not been abandoned, it is no longer considered abandoned after the thread releases its ownership.
This restores normal behavior if a handle to the mutex object is subsequently specified in a wait function.
 
如果一个线程终止时没有释放拥有Mutex Object对象权利时,Mutex Object被认为是被抛弃的。在Mutex Object 等待中的线程可以获取到一个被丢弃的Mutex Object。但是wait函数将返回WAIT_ABANDONED 值来暗示
该Mutex Object已经被抛弃。一个被抛弃的Mutex Object意味着一个错误已经产生。被Mutex Object保护的共享资源将处于为定义的状态。
 
 
 Note that critical section objects provide synchronization similar to that provided by mutex objects, except that critical section objects can be used only by the threads of a single process.


 特别注意:
 Critical  Section Object 和Mutex Object最大的区别在于:Critical  Section Object仅仅只能在一个进程中的所有线程使用,而Mutex Object 可以被多个进程中的线程使用。
 
 
 
 
 WaitForSingleObject function
 Waits until the specified object is in the signaled state or the time-out interval elapses.
 WORD WINAPI WaitForSingleObject
 (
  _In_ HANDLE hHandle,
  _In_ DWORD  dwMilliseconds
);
 dwMilliseconds [in]
The time-out interval, in milliseconds. 
If a nonzero value is specified, the function waits until the object is signaled or the interval elapses. 
If dwMilliseconds is zero, the function does not enter a wait state if the object is not signaled; it always returns immediately. 
If dwMilliseconds is INFINITE, the function will return only when the object is signaled.


The WaitForSingleObject function checks the current state of the specified object. 
If the object's state is nonsignaled, the calling thread enters the wait state until the object is signaled or the time-out interval elapses.
WaitForSingleObject()函数将检查指定对象的状态。

如果对象的状态是无信号的,调用线程将阻塞直到对象有信号或者超时。


UsingMutexObjects.cpp:

#include <windows.h>
#include <stdio.h>

#define THREADCOUNT 2

HANDLE ghMutex; 

DWORD WINAPI WriteToDatabase( LPVOID );
DWORD WINAPI WriteToDatabaseWithoutMutexObject( LPVOID );

int main( void )
{
    HANDLE aThread[THREADCOUNT*2];
    DWORD ThreadID;
    int i;

    // Create a mutex with no initial owner
	//创建一个没有名字的Mutex Object对象。该Mutex Object不存在名字,所以其他进程中的线程无法获取到该Mutex Object的权利。
    ghMutex = CreateMutex( 
        NULL,              // default security attributes
        FALSE,             // initially not owned
        NULL);             // unnamed mutex

    if (ghMutex == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }

    // Create worker threads
	//创建多个共同协作互斥完成打印的线程。
    for( i=0; i < THREADCOUNT; i++ )
    {
        aThread[i] = CreateThread( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) WriteToDatabase, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return 1;
        }
    }
	 // Create worker threads  Without Mutex Object
    for( i=2; i < THREADCOUNT*2; i++ )
    {
        aThread[i] = CreateThread( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) WriteToDatabaseWithoutMutexObject, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return 1;
        }
    }
    // Wait for all threads to terminate
	// 等待所有线程的终止
    WaitForMultipleObjects(THREADCOUNT*2, aThread, TRUE, INFINITE);

    // Close thread and mutex handles

    for( i=0; i < THREADCOUNT*2; i++ )
        CloseHandle(aThread[i]);

    CloseHandle(ghMutex);

    return 0;
}
DWORD WINAPI WriteToDatabaseWithoutMutexObject( LPVOID lpParam )
{
	DWORD dwCount=0;
	while( dwCount < 20 )
    { 
		 // TODO: Write to the database
        printf("Thread %d writing to database without mutex object...\n", 
                GetCurrentThreadId());
        dwCount++;
	}
	return true;
}
DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{ 
    // lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwCount=0, dwWaitResult; 

    // Request ownership of mutex.

    while( dwCount < 20 )
    { 
        dwWaitResult = WaitForSingleObject( 
            ghMutex,    // handle to mutex
            INFINITE);  // no time-out interval
        switch (dwWaitResult) 
        {
            // The thread got ownership of the mutex
			//The state of the specified object is signaled. 
			//WaitForSingleObject()函数返回值标志着该线程获取到Mutex Object
            case WAIT_OBJECT_0: 
                __try { 
                    // TODO: Write to the database
                    printf("Thread %d writing to database...\n", 
                            GetCurrentThreadId());
                    dwCount++;
                } 

                __finally { 
                    // Release ownership of the mutex object
                    if (! ReleaseMutex(ghMutex)) 
                    { 
                        // Handle error.
                    } 
                } 
                break; 

            // The thread got ownership of an abandoned mutex
            // The database is in an indeterminate state
            case WAIT_ABANDONED: 
                return FALSE; 
        }
    }
    return TRUE; 
}
运行结果:




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:123022次
    • 积分:2551
    • 等级:
    • 排名:第14964名
    • 原创:120篇
    • 转载:4篇
    • 译文:21篇
    • 评论:11条
    最新评论