win下多线程,同步等简单应用
来源:互联网 发布:js操作input file 编辑:程序博客网 时间:2024/05/29 09:52
1. 互斥量,Mutex
Qt下环境需要pro下加
DEFINES -= UNICODE
- #include <Windows.h>
- #include <iostream>
- using namespace std;
- DWORD WINAPI Thread1(LPVOID lpParmeter);
- DWORD WINAPI Thread2(LPVOID lpParmeter);
- static HANDLE g_hMutex = INVALID_HANDLE_VALUE;
- static int g_iCnt = 100;
- int main()
- {
- HANDLE hThread1 = INVALID_HANDLE_VALUE;
- HANDLE hThread2 = INVALID_HANDLE_VALUE;
- g_hMutex = CreateMutex(NULL, FALSE, "Mutex");
-
-
-
- if (!g_hMutex)
- {
- cout << "Failed to CreateMutex !" << endl;
- return 0;
- }
- hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
- hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
- Sleep(4000);
- CloseHandle(hThread1);
- CloseHandle(hThread2);
- system("PAUSE");
- return 0;
- }
- DWORD WINAPI Thread1(LPVOID lpParmeter)
- {
- while (true)
- {
-
- WaitForSingleObject(g_hMutex, INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "Thread1:" << g_iCnt-- << endl;
- ReleaseMutex(g_hMutex);
- }
- else
- {
- ReleaseMutex(g_hMutex);
- break;
- }
- }
- return 0;
- }
- DWORD WINAPI Thread2(LPVOID lpParameter)
- {
- while (true)
- {
-
- WaitForSingleObject(g_hMutex,INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "thread2:" << g_iCnt-- << endl;
- ReleaseMutex(g_hMutex);
- }
- else
- {
- ReleaseMutex(g_hMutex);
- break;
- }
- }
- return 0;
- }
几个注意的地方:
(1)互斥量为内核对象,能够与其他线程或特殊事件取得同步;
(2)速度比临界区要慢;
(3)互斥量对象与所有其它内核对象的不同之处在于它是被线程所拥有的,互斥量对象除了记录当前信号状态外,还要记住此时那个线程拥有它。
(4)这个常来被运用于限制程序启动次数!
2.事件 Event
- #include <Windows.h>
- #include <iostream>
- using namespace std;
- DWORD WINAPI Thread1(LPVOID lpParmeter);
- DWORD WINAPI Thread2(LPVOID lpParmeter);
- static HANDLE g_hEvent = INVALID_HANDLE_VALUE;
- static int g_iCnt = 100;
- int main()
- {
- HANDLE hThread1 = INVALID_HANDLE_VALUE;
- HANDLE hThread2 = INVALID_HANDLE_VALUE;
- g_hEvent = CreateEvent(NULL, false, false, "Event");
- if (!g_hEvent)
- {
- cout << "Failed to CreateEvent !" << endl;
- return 0;
- }
-
-
-
-
-
-
-
-
- hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
- hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
- SetEvent(g_hEvent);
- Sleep(4000);
- CloseHandle(hThread1);
- CloseHandle(hThread2);
- system("PAUSE");
- return 0;
- }
- DWORD WINAPI Thread1(LPVOID lpParmeter)
- {
- while (true)
- {
-
- WaitForSingleObject(g_hEvent, INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "Thread1:" << g_iCnt-- << endl;
- SetEvent(g_hEvent);
- }
- else
- {
- SetEvent(g_hEvent);
- break;
- }
- }
- return 0;
- }
- DWORD WINAPI Thread2(LPVOID lpParameter)
- {
- while (true)
- {
-
- WaitForSingleObject(g_hEvent,INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "thread2:" << g_iCnt-- << endl;
- SetEvent(g_hEvent);
- }
- else
- {
- SetEvent(g_hEvent);
- break;
- }
- }
- return 0;
- }
几个注意的地方:
(1).和Mutex使用差不多,只有细微的差别;
(2).可以使用SetEvent或ResetEvent改变其状态;
(3).在应用程序中任意一处没有正确的按照规则调用SetEvent或ResetEvent,将达不到同步或互斥的目的;
(4).一般来说,都是利用Event来进行同步,而不是我们这里的让它来达到互斥;
(5).Event处于无信号状态时,相关线程或进程退出,系统并不会尝试将其置为有信号状态;
3.临界区 CRITICAL_SECTION
- #include <Windows.h>
- #include <iostream>
- using namespace std;
- DWORD WINAPI Thread1(LPVOID lpParmeter);
- DWORD WINAPI Thread2(LPVOID lpParmeter);
- CRITICAL_SECTION g_CriticalSection;
- static int g_iCnt = 100;
- int main()
- {
- HANDLE hThread1 = INVALID_HANDLE_VALUE;
- HANDLE hThread2 = INVALID_HANDLE_VALUE;
- InitializeCriticalSection(&g_CriticalSection);
- hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
- hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
- Sleep(4000);
- CloseHandle(hThread1);
- CloseHandle(hThread2);
- DeleteCriticalSection(&g_CriticalSection);
- system("PAUSE");
- return 0;
- }
- DWORD WINAPI Thread1(LPVOID lpParmeter)
- {
- while (true)
- {
- EnterCriticalSection(&g_CriticalSection);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "Thread1:" << g_iCnt-- << endl;
- LeaveCriticalSection(&g_CriticalSection);
- }
- else
- {
- LeaveCriticalSection(&g_CriticalSection);
- break;
- }
- }
- return 0;
- }
- DWORD WINAPI Thread2(LPVOID lpParameter)
- {
- while (true)
- {
- EnterCriticalSection(&g_CriticalSection);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "thread2:" << g_iCnt-- << endl;
- LeaveCriticalSection(&g_CriticalSection);
- }
- else
- {
- LeaveCriticalSection(&g_CriticalSection);
- break;
- }
- }
- return 0;
- }
几个注意的地方:
(1).比Mutex速度快;
(2).临界区在线程内的分配必须是全局的;
(3). 临界区一次只允许一个线程访问;
4.信号量Semaphore
首先说说那些关于信号量那些不得不让人伤心的事情,因为笔者大学不好学习,非常调皮,而信号量又是老师最讨论及考试的话题之一,所以我觉得这个东西非常扯淡,非常影响情绪,于是放在最后。------以上是为题外话。
为什么大学老师总是喜欢信号量呢?
因为这是一个生产者-消费者模型,并且很多计算机问题都可以看做是生产者-消费者的问题,是同步最易理解的模型。
关于理论上的知识,我就不说了,书里面很多的。
还有我不是很想实现生产者-消费者的模型,就用其他例子代替了。这个有点不负责任。
- #include <Windows.h>
- #include <iostream>
- #include <vector>
- using namespace std;
- DWORD WINAPI Thread1(LPVOID lpParmeter);
- DWORD WINAPI Thread2(LPVOID lpParmeter);
- static HANDLE g_hSemaphore = INVALID_HANDLE_VALUE;;
- static int g_iCnt = 100;
- int main()
- {
- HANDLE hThread1 = INVALID_HANDLE_VALUE;
- HANDLE hThread2 = INVALID_HANDLE_VALUE;
-
-
-
-
-
- g_hSemaphore = CreateSemaphore(NULL, 1, 1, "Semaphore");
-
- if (g_hSemaphore == INVALID_HANDLE_VALUE)
- {
- cout << "Failed to Create Semaphore!" << endl;
- return 0;
- }
- hThread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
- hThread2 = CreateThread(NULL, 0, Thread2, NULL, 0, NULL);
- Sleep(4000);
- CloseHandle(hThread1);
- CloseHandle(hThread2);
- system("PAUSE");
- return 0;
- }
- DWORD WINAPI Thread1(LPVOID lpParmeter)
- {
- while (true)
- {
- WaitForSingleObject(g_hSemaphore, INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "Thread1:" << g_iCnt-- << endl;
- ReleaseSemaphore(g_hSemaphore, 1, NULL);
- }
- else
- {
- break;
- }
- }
- return 0;
- }
- DWORD WINAPI Thread2(LPVOID lpParameter)
- {
- while (true)
- {
- WaitForSingleObject(g_hSemaphore, INFINITE);
- if (g_iCnt > 0)
- {
- Sleep(20);
- cout << "thread2:" << g_iCnt-- << endl;
- ReleaseSemaphore(g_hSemaphore, 1, NULL);
- }
- else
- {
- break;
- }
- }
- return 0;
- }
几个注意的地方:
信号量内核对象对线程的同步方式与前面几种不同,它允许多个线程在同一时刻访问某一资源,但是需要限制同一时刻访问此资源的最大线程数目。
总结: 线程规模 = CPU 数 * 2 + 1
代码通过VS2005编译,运行成功,如有什么疑问,请各位看官大方赐教。