线程同步(1) - 用户模式下的线程同步

来源:互联网 发布:程序员健康指南 编辑:程序博客网 时间:2024/05/29 19:33

(1)       用户模式的等待

DWORD WaitForSingleObject(

HANDLE hHandle,        // handle to object to wait for

DWORD dwMilliseconds   // time-out interval in milliseconds

);

 

DWORD WaitForMultipleObjects(
  DWORD nCount,             // number of handles in the handle array
  CONST HANDLE *lpHandles// pointer to the object-handle array
  BOOL fWaitAll,            // wait flag
  DWORD dwMilliseconds      // time-out interval in milliseconds
);

 

(2)       用户模式的事件

HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
                      // pointer to security attributes
BOOL bManualReset// flag for manual-reset event
BOOL bInitialState, // flag for initial state
LPCTSTR lpName      // pointer to event-object name
);
 

示例代码:

#include <stdio.h>

#include <process.h>

#include <windows.h>

 

UINT WINAPI ThreadProc( LPVOID lpParameter )

{

         printf("Enter Second Thread!\n");

         HANDLE hEvent = *(PHANDLE)lpParameter;

         Sleep(1000);

         printf("Leave Second Thread!\n");

         //激发事件

         SetEvent(hEvent);

         return 0;

}

 

int main(void)

{

         printf("Enter Main Thread!\n");

         //定义一个自动重置的,未激发的事件对象

         HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 

         HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, &hEvent, 0, NULL);

         //等待该事件激发

         WaitForSingleObject(hEvent, INFINITE);

         printf("Leave Main Thread!\n");

         return 0;

}

 

(3)       用户模式的信号灯

信号灯内部有个计数器,可以理解信号灯内部有N个灯泡,如果有一个灯泡亮着,就代表信号灯处于激发状态,如果全部熄灭,就代表信号灯处于未激发状态。

 

创建信号灯:

HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
                       // pointer to security attributes
  LONG lInitialCount// initial count
  LONG lMaximumCount// maximum count
  LPCTSTR lpName       // pointer to semaphore-object name
);
 
增加信号灯的计数器:
BOOL ReleaseSemaphore(
  HANDLE hSemaphore,   // handle to the semaphore object
  LONG lReleaseCount// amount to add to current count
  LPLONG lpPreviousCount   // address of previous count
);
 

对信号灯执行一次等待操作,就会减少一个计数,就相当于熄灭一个灯泡。当计数为0时,也就是所有灯泡都熄灭时,当前线程进入睡眠状态,直到信号灯变成激发状态或者超时。

 

示例代码:

#include <windows.h>

#include <stdio.h>

#include <process.h>

 

UINT WINAPI ThreadProc(LPVOID lpParam)

{

         printf("Enter Second Thread!\n");

         HANDLE hSemaphore = *(PHANDLE)lpParam;

         Sleep(5000);

         printf("Leave Second Thread!\n");

         //将信号灯计数加1,使之成为激发状态

         ReleaseSemaphore(hSemaphore, 1, NULL);

         return 0;

}

 

int main(void)

{

         printf("Enter Main Thread!\n");

         //创建信号灯

         HANDLE hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);

         //此时信号灯计数为2,处于激发状态

         WaitForSingleObject(hSemaphore, INFINITE);

         //此时信号灯计数为1,处于激发状态

         WaitForSingleObject(hSemaphore, INFINITE);

         //创建新线程

         HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, &hSemaphore, 0, NULL);

         //此时信号灯计数为0,处于未激发状态,为了等待信号灯,线程被挂起

         WaitForSingleObject(hSemaphore, INFINITE);

         printf("Leave Main Thread!\n");

         return 0;

}

 

(4)       用户模式的互斥体

获得了互斥体之后,同一个线程中可以递归获得互斥体。所谓递归获得互斥体就是得到互斥体的线程还可以再次获得这个互斥体,或者说互斥体对于已经获得互斥体的线程不产生

互斥关系。

 

创建互斥体:

HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
                       // pointer to security attributes
BOOL bInitialOwner// flag for initial ownership
LPCTSTR lpName       // pointer to mutex-object name
       );

 

释放互斥体:

BOOL ReleaseMutex(
  HANDLE hMutex   // handle to mutex object
);

 

示例代码:

#include <windows.h>

#include <process.h>

#include <stdio.h>

 

UINT WINAPI ThreadProc1(LPVOID lparam)

{

         HANDLE hMutex = *(PHANDLE)lparam;

         //等待互斥体

         WaitForSingleObject(hMutex, INFINITE);

         //对于同一个线程,已经获得了互斥体,还可以多次获取

         WaitForSingleObject(hMutex, INFINITE);

         printf("Enter  Thread1!\n");

         Sleep(2000);

         printf("Leave  Thread1!\n");

         //释放互斥体

         ReleaseMutex(hMutex);

         return 0;

}

 

UINT WINAPI ThreadProc2(LPVOID lparam)

{       

         HANDLE hMutex = *(PHANDLE)lparam;

         WaitForSingleObject(hMutex, INFINITE);

         printf("Enter  Thread2!\n");

         Sleep(2000);

         printf("Leave  Thread2!\n");

         ReleaseMutex(hMutex);

         return 0;

}

 

int main(void)

{

         printf("Enter Main Thread!\n");

         //创建互斥体

         HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);

         HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, &hMutex, 0, NULL);

         HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, &hMutex, 0, NULL);

         Sleep(6000);

         printf("Leave Main Thread!\n");

         return 0;

}

 

(5)       等待线程完成

还有一种同步对象,就是线程对象。每个线程同样有两个状态,激发状态和未激发状态。当线程在运行中的时候,是未激发状态。当线程终止后,线程处于激发状态。可以用WaitFor*函数对线程句柄进行等待。

 

示例代码:

#include <windows.h>

#include <stdio.h>

#include <process.h>

 

UINT WINAPI ThreadProc(LPVOID lpParam)

{

         printf("Enter ThreadProc!\n");

         Sleep(5000);

         printf("Leave ThreadProc!\n");

         return 0;

}

 

int main(void)

{

         //创建两个字线程

         HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL);

         HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL);

         //主线程等待两个字线程结束

         HANDLE hThread[2] = {hThread1, hThread2};

         WaitForMultipleObjects(2, hThread, TRUE, INFINITE);

         return 0;

}


0 0
原创粉丝点击