Windows线程同步
来源:互联网 发布:javascript读取excel文件 编辑:程序博客网 时间:2024/06/04 19:00
以下内容摘抄自《Visual C++开发技术大全》,为学习笔记。
线程同步的方法有很多,最常用的有
互斥(CMutex)
临界(CriticalSection)
信号量(Semaphore)
事件(Event)等。
这4种方式分别在 Win32 和 MFC 两种方式下各有一种实现, MFC 方式是对 Win32方式的封装,使用起来更加简便。
互斥(CMutex)就是一个线程对共享资源进行访问时排斥其他的线程。互斥对象可通过CreateMutex 函数创建,在程序运行时只有拥有互斥对象的线程有访问共享资源的权利。如果线程对共享资源使用完了,要用ReleaseMutex 函数交出互斥对象,好让其他线程拥有对共享资源的访问权利。
#include <windows.h>#include <stdio.h>#define THREADCOUNT 2HANDLE ghMutex; DWORD WINAPI WriteToDatabase( LPVOID );int main( void ){ HANDLE aThread[THREADCOUNT]; DWORD ThreadID; int i; // Create a mutex with no initial owner 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; } } // Wait for all threads to terminate WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); // Close thread and mutex handles for( i=0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); CloseHandle(ghMutex); return 0;}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 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; }信号量允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目,超出这个最大数的线程将不允许访问此资源。主要通过CreateSemaphore 函数来实现。
HANDLE WINAPI CreateSemaphore( _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, _In_ LONG lInitialCount, _In_ LONG lMaximumCount, _In_opt_ LPCTSTR lpName);返回值:成功返回信号量句柄,失败返回 NULL;
参数: lpSemaphoreAttributes 安全属性
lInitialCount 正在运行线程的数量
lMaximumCount 允许的最大数量
lpName 信号量名称
从函数原型可以看出,创建信号量时需要指出允许的最大资源计数和当前可用资源计数,每增加一个访问共享资源的线程,当前可以资源计数就减一。
#include <windows.h>#include <stdio.h>#define MAX_SEM_COUNT 10#define THREADCOUNT 12HANDLE ghSemaphore;DWORD WINAPI ThreadProc( LPVOID );int main( void ){ HANDLE aThread[THREADCOUNT]; DWORD ThreadID; int i; // Create a semaphore with initial and max counts of MAX_SEM_COUNT ghSemaphore = CreateSemaphore( NULL, // default security attributes MAX_SEM_COUNT, // initial count MAX_SEM_COUNT, // maximum count NULL); // unnamed semaphore if (ghSemaphore == NULL) { printf("CreateSemaphore 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) ThreadProc, 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, aThread, TRUE, INFINITE); // Close thread and semaphore handles for( i=0; i < THREADCOUNT; i++ ) CloseHandle(aThread[i]); CloseHandle(ghSemaphore); return 0;}DWORD WINAPI ThreadProc( LPVOID lpParam ){ // lpParam not used in this example UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; BOOL bContinue=TRUE; while(bContinue) { // Try to enter the semaphore gate. dwWaitResult = WaitForSingleObject( ghSemaphore, // handle to semaphore 0L); // zero-second time-out interval switch (dwWaitResult) { // The semaphore object was signaled. case WAIT_OBJECT_0: // TODO: Perform task printf("Thread %d: wait succeeded\n", GetCurrentThreadId()); bContinue=FALSE; // Simulate thread spending time on task Sleep(5); // Release the semaphore when task is finished if (!ReleaseSemaphore( ghSemaphore, // handle to semaphore 1, // increase count by one NULL) ) // not interested in previous count { printf("ReleaseSemaphore error: %d\n", GetLastError()); } break; // The semaphore was nonsignaled, so a time-out occurred. case WAIT_TIMEOUT: printf("Thread %d: wait timed out\n", GetCurrentThreadId()); break; } } return TRUE;}用事件 (Event)来实现线程的同步和互斥很相似。SetEvent可以看做是对某项特定任务完成的通知,先用CreateEvent 函数创建一个事件句柄,然后启动使用 WaitForSingleObject 函数来等待事件发生。
#include <windows.h>#include <stdio.h>#define THREADCOUNT 4 HANDLE ghWriteEvent; HANDLE ghThreads[THREADCOUNT];DWORD WINAPI ThreadProc(LPVOID);void CreateEventsAndThreads(void) { int i; DWORD dwThreadID; // Create a manual-reset event object. The write thread sets this // object to the signaled state when it finishes writing to a // shared buffer. ghWriteEvent = CreateEvent( NULL, // default security attributes TRUE, // manual-reset event FALSE, // initial state is nonsignaled TEXT("WriteEvent") // object name ); if (ghWriteEvent == NULL) { printf("CreateEvent failed (%d)\n", GetLastError()); return; } // Create multiple threads to read from the buffer. for(i = 0; i < THREADCOUNT; i++) { // TODO: More complex scenarios may require use of a parameter // to the thread procedure, such as an event per thread to // be used for synchronization. ghThreads[i] = CreateThread( NULL, // default security 0, // default stack size ThreadProc, // name of the thread function NULL, // no thread parameters 0, // default startup flags &dwThreadID); if (ghThreads[i] == NULL) { printf("CreateThread failed (%d)\n", GetLastError()); return; } }}void WriteToBuffer(VOID) { // TODO: Write to the shared buffer. printf("Main thread writing to the shared buffer...\n"); // Set ghWriteEvent to signaled if (! SetEvent(ghWriteEvent) ) { printf("SetEvent failed (%d)\n", GetLastError()); return; }}void CloseEvents(){ // Close all event handles (currently, only one global handle). CloseHandle(ghWriteEvent);}int main( void ){ DWORD dwWaitResult; // TODO: Create the shared buffer // Create events and THREADCOUNT threads to read from the buffer CreateEventsAndThreads(); // At this point, the reader threads have started and are most // likely waiting for the global event to be signaled. However, // it is safe to write to the buffer because the event is a // manual-reset event. WriteToBuffer(); printf("Main thread waiting for threads to exit...\n"); // The handle for each thread is signaled when the thread is // terminated. dwWaitResult = WaitForMultipleObjects( THREADCOUNT, // number of handles in array ghThreads, // array of thread handles TRUE, // wait until all are signaled INFINITE); switch (dwWaitResult) { // All thread objects were signaled case WAIT_OBJECT_0: printf("All threads ended, cleaning up for application exit...\n"); break; // An error occurred default: printf("WaitForMultipleObjects failed (%d)\n", GetLastError()); return 1; } // Close the events to clean up CloseEvents(); return 0;}DWORD WINAPI ThreadProc(LPVOID lpParam) { // lpParam not used in this example. UNREFERENCED_PARAMETER(lpParam); DWORD dwWaitResult; printf("Thread %d waiting for write event...\n", GetCurrentThreadId()); dwWaitResult = WaitForSingleObject( ghWriteEvent, // event handle INFINITE); // indefinite wait switch (dwWaitResult) { // Event object was signaled case WAIT_OBJECT_0: // // TODO: Read from the shared buffer // printf("Thread %d reading from buffer\n", GetCurrentThreadId()); break; // An error occurred default: printf("Wait error (%d)\n", GetLastError()); return 0; } // Now that we are done reading the buffer, we could use another // event to signal that this thread is no longer reading. This // example simply uses the thread handle for synchronization (the // handle is signaled when the thread terminates.) printf("Thread %d exiting\n", GetCurrentThreadId()); return 1;}
0 0
- windows ce 线程同步
- Windows线程同步方法
- windows线程同步 基础
- windows 线程同步机制
- windows线程同步方法
- windows线程同步
- Windows线程同步API
- Windows 线程同步
- Windows线程同步API
- Windows线程同步API
- windows线程同步方法
- Windows线程同步方式
- Windows中线程同步
- Windows 线程同步
- Windows线程间同步
- Windows线程同步API
- Windows线程同步
- Windows线程同步总结
- 第2章:R的数据可视化,各种图表,常用统计量计算
- 将两个排好序的数组,合并到另外一个数组中,并且合并之后的数组也是有序的。
- jQuery 增加 删除 修改select option .
- 给定一个二进制数,要求循环移位,在原二进制数中操作(C语言)
- 读写外挂
- Windows线程同步
- 指针
- ndroid 最火框架XUtils
- C语言的字符串转为OC中的字符串,控制台输入用户名和密码,判断输入的用户名是否是@“Frank”, 密码 是否是 @“lanou”, 如果用户名和密码都正确,则输出登录成功, 否则输出登录失败.
- c++静态库和动态库
- read 系统调用剖析 (vfs分析 address_space page cache)
- 随机为一维数组赋值,找出其中的第二大值
- 【菜鸟】 回忆初中及学编程中艰辛过程、感言
- c++对象模型