孙鑫 MFC 学习 线程间的通讯

  1. CriticalSection(同一进程间的线程通信,速度快但是可能会产生死锁)
CriticalSection
 1 #include <windows.h>
2 #include <iostream>
3
4 using namespace std;
5
6 DWORD WINAPI Fun1Proc(LPVOID lpParameter);
7 DWORD WINAPI Fun2Proc(LPVOID lpParameter);
8
9 int tickets=10;
10 CRITICAL_SECTION g_cs;
11
12 void main()
13 {
14 cout << "Main thread is running." << endl;
15 InitializeCriticalSection(&g_cs);
16
17 HANDLE hThread1;
18 HANDLE hThread2;
19 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
20 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
21
22 CloseHandle(hThread1);
23 CloseHandle(hThread2);
24
25 Sleep(2000);
26 DeleteCriticalSection(&g_cs);
27 }
28
29 DWORD WINAPI Fun1Proc(LPVOID lpParameter)
30 {
31 while(TRUE)
32 {
33 EnterCriticalSection(&g_cs);
34 if(tickets>0)
35 {
36 cout<<"thread1 sell ticket : "<<tickets--<<endl;
37 }
38 LeaveCriticalSection(&g_cs);
39 Sleep(1);//注意这里的睡眠。离开临界区如果没有这个睡眠的话,只有这一个线程在输出
40
41 if (tickets <= 0)
42 {
43 break;
44 }
45 }
46
47 return 0;
48 }
49
50 DWORD WINAPI Fun2Proc(LPVOID lpParameter)
51 {
52 while(TRUE)
53 {
54 EnterCriticalSection(&g_cs);
55 if(tickets>0)
56 {
57 cout<<"thread2 sell ticket : "<<tickets--<<endl;
58 }
59 LeaveCriticalSection(&g_cs);
60 Sleep(1);
61
62 if (tickets <= 0)
63 {
64 break;
65 }
66 }
67
68 return 0;
69 }

MFC提供了很多功能完备的类,我用MFC实现了临界区。MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是非常简单的。只需在线程函数中用CCriticalSection类成员函数Lock()UnLock()标定出被保护代码片段即可。Lock()后代码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。

下面是产生死锁的一段完整代码

2. CriticalSection - DeadLock

DeadLock
 1 #include <windows.h>
2 #include <iostream>
3
4 using namespace std;
5
6 DWORD WINAPI Fun1Proc(LPVOID lpParameter);
7 DWORD WINAPI Fun2Proc(LPVOID lpParameter);
8
9 int tickets=10;
10 CRITICAL_SECTION g_csA;
11 CRITICAL_SECTION g_csB;
12
13 void main()
14 {
15 cout << "Main thread is running." << endl;
16 InitializeCriticalSection(&g_csA);
17 InitializeCriticalSection(&g_csB);
18
19 HANDLE hThread1;
20 HANDLE hThread2;
21 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
22 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
23
24 CloseHandle(hThread1);
25 CloseHandle(hThread2);
26
27 Sleep(2000);
28 DeleteCriticalSection(&g_csA);
29 DeleteCriticalSection(&g_csB);
30 }
31
32 DWORD WINAPI Fun1Proc(LPVOID lpParameter)
33 {
34 while(TRUE)
35 {
36 EnterCriticalSection(&g_csA);
37 Sleep(1000);
38 EnterCriticalSection(&g_csB);
39 if(tickets>0)
40 {
41 cout<<"thread1 sell ticket : "<<tickets--<<endl;
42 }
43 LeaveCriticalSection(&g_csB);
44 LeaveCriticalSection(&g_csA);
45 Sleep(1);
46
47 if (tickets <= 0)
48 {
49 break;
50 }
51 }
52
53 return 0;
54 }
55
56 DWORD WINAPI Fun2Proc(LPVOID lpParameter)
57 {
58 while(TRUE)
59 {
60 EnterCriticalSection(&g_csB);
61 Sleep(1000);
62 EnterCriticalSection(&g_csA);
63 if(tickets>0)
64 {
65 cout<<"thread2 sell ticket : "<<tickets--<<endl;
66 }
67 LeaveCriticalSection(&g_csA);
68 LeaveCriticalSection(&g_csB);
69 Sleep(1);
70
71 if (tickets <= 0)
72 {
73 break;
74 }
75 }
76
77 return 0;
78 }



 

3. Mutex

Mutex
 1 #include <windows.h>
2 #include <iostream>
3
4 using namespace std;
5
6 DWORD WINAPI Fun1Proc(LPVOID lpParameter);
7 DWORD WINAPI Fun2Proc(LPVOID lpParameter);
8
9 int tickets=10;
10 HANDLE hMutex;
11
12 void main()
13 {
14 cout << "Main thread is running." << endl;
15 hMutex=CreateMutex(NULL,FALSE,NULL);
16
17 HANDLE hThread1;
18 HANDLE hThread2;
19 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
20 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
21 CloseHandle(hThread1);
22 CloseHandle(hThread2);
23
24 Sleep(1000);
25 }
26
27 DWORD WINAPI Fun1Proc(LPVOID lpParameter)
28 {
29 while(TRUE)
30 {
31 WaitForSingleObject(hMutex,INFINITE);
32 if(tickets>0)
33 {
34 Sleep(1);
35 cout<<"thread1 sell ticket : "<<tickets--<<endl;
36 }
37 ReleaseMutex(hMutex);
38
39 if (tickets == 0)
40 {
41 break;
42 }
43 }
44
45 return 0;
46 }
47
48 DWORD WINAPI Fun2Proc(LPVOID lpParameter)
49 {
50 while(TRUE)
51 {
52 WaitForSingleObject(hMutex,INFINITE);
53 if(tickets>0)
54 {
55 Sleep(1);
56 cout<<"thread2 sell ticket : "<<tickets--<<endl;
57 }
58 ReleaseMutex(hMutex);
59
60 if (tickets == 0)
61 {
62 break;
63 }
64 }
65
66 return 0;
67 }

输出结果



4. Event

Event
 1 #include <windows.h>
2 #include <iostream>
3
4 using namespace std;
5
6 DWORD WINAPI Fun1Proc(LPVOID lpParameter);
7 DWORD WINAPI Fun2Proc(LPVOID lpParameter);
8
9 int tickets=10;
10 HANDLE g_hEvent;
11
12 void main()
13 {
14 cout << "Main thread is running." << endl;
15 g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
16 SetEvent(g_hEvent);
17
18
19 HANDLE hThread1;
20 HANDLE hThread2;
21 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
22 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
23 CloseHandle(hThread1);
24 CloseHandle(hThread2);
25
26 Sleep(1000);
27 }
28
29 DWORD WINAPI Fun1Proc(LPVOID lpParameter)
30 {
31 while(TRUE)
32 {
33 WaitForSingleObject(g_hEvent,INFINITE);//如果是自动重置,那么在获得句柄后会将g_hEvent设置为无信号状态
34 if(tickets>0)
35 {
36 Sleep(1);
37 cout<<"thread1 sell ticket : "<<tickets--<<endl;
38 }
39 SetEvent(g_hEvent);
40
41 if (tickets <= 0)
42 {
43 break;
44 }
45 }
46
47 return 0;
48 }
49
50 DWORD WINAPI Fun2Proc(LPVOID lpParameter)
51 {
52 while(TRUE)
53 {
54 WaitForSingleObject(g_hEvent,INFINITE);
55 if(tickets>0)
56 {
57 Sleep(1);
58 cout<<"thread2 sell ticket : "<<tickets--<<endl;
59 }
60 SetEvent(g_hEvent);
61
62 if (tickets <= 0)
63 {
64 break;
65 }
66 }
67
68 return 0;
69 }

 
事件对象也属于内核对象,包含一个使用计数,一个用于指明该事件是一个自动重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。
有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程


Semaphore

posted @ 2012-03-30 15:17  hanyuanbo  阅读(870)  评论(0编辑  收藏  举报