同步与互斥

如果是问windows环境下同步的方法有哪些?

回答:互斥锁、事件、互斥量、信号量;

同步,意在合作的关系,如:线程A和线程B,线程A执行完某操作后,立马通知线程B(线程B之前应该是挂起状态)执行。

互斥,意在对资源的唯一占有的强调,如:线程A和线程B,对于全局变量或静态变量(共享内存区)的唯一占有。线程A在访问共享内存区时,不运行线程B访问。反之亦然。互斥有同步的形式表现:线程A占有共享内存区完成访问后,系统会概率性的跳到线程B挂起的状态,这时共享内存区允许访问。

  不同:

    互斥不关心合作,重点在维护共享内存区的唯一访问条件。

           同步重点在合作。

所以,上面的问题回答是不正确的。同步的方法只有事件和信号量。【具体的方法描述:该链接

如果,不用同步方法做出同步效果,可以使用线程通信 技术来完成。

如下:模拟五个不同子线程使用线程通信实现同步效果的程序。

  1 #include <windows.h>
  2 #include <iostream>
  3 using namespace std;
  4 
  5 long g_nNum = 0;
  6 const int THREAD_NUM = 5;
  7 DWORD WINAPI Fun1 (LPVOID lpThreadParameter);
  8 DWORD WINAPI Fun2 (LPVOID lpThreadParameter);
  9 DWORD WINAPI Fun3 (LPVOID lpThreadParameter);
 10 DWORD WINAPI Fun4 (LPVOID lpThreadParameter);
 11 DWORD WINAPI Fun5 (LPVOID lpThreadParameter);
 12 
 13 DWORD    nHandleThreadID[THREAD_NUM] = {0};
 14 HANDLE  handle[THREAD_NUM];    
 15 
 16 #define TALK_MESSAGE WM_USER + 1
 17 
 18 
 19 int main()
 20 {
 21     int p[THREAD_NUM] = {0};
 22     for(int i=0;i<THREAD_NUM;i++)
 23     {
 24         switch(i)
 25         {
 26         case 0:
 27             handle[i] = (HANDLE)CreateThread(NULL, 0, Fun1, 0, 0, NULL);
 28             nHandleThreadID[i] = GetThreadId(handle[i]);
 29             break;
 30         case 1:
 31             handle[i] = (HANDLE)CreateThread(NULL, 0, Fun2, 0, 0, NULL);
 32             nHandleThreadID[i] = GetThreadId(handle[i]);
 33             break;
 34         case 2:
 35             handle[i] = (HANDLE)CreateThread(NULL, 0, Fun3, 0, 0, NULL);
 36             nHandleThreadID[i] = GetThreadId(handle[i]);
 37             break;
 38         case 3:
 39             handle[i] = (HANDLE)CreateThread(NULL, 0, Fun4, 0, 0, NULL);
 40             nHandleThreadID[i] = GetThreadId(handle[i]);
 41             break;
 42         case 4:
 43             handle[i] = (HANDLE)CreateThread(NULL, 0, Fun5, 0, 0, NULL);
 44             nHandleThreadID[i] = GetThreadId(handle[i]);
 45             break;
 46         }
 47     }
 48 
 49     WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
 50 
 51     return 0;
 52 }
 53 
 54 
 55 DWORD WINAPI Fun1(LPVOID lpThreadParameter)
 56 {
 57     Sleep(10); // 等待Fun2、Fun3...的消息队列创建.
 58 
 59     DWORD nThreadId = GetCurrentThreadId();
 60     g_nNum++; //访问全局变量,所有线程共享内存区
 61     printf("线程编号为%d  全局资源值为%d
", nThreadId, g_nNum); 
 62     PostThreadMessage (nHandleThreadID[1], TALK_MESSAGE, 0, 0);
 63     
 64     return 0;
 65 }
 66 
 67 DWORD WINAPI Fun2 (LPVOID lpThreadParameter)
 68 {
 69     MSG msg;
 70     while( GetMessage(&msg, 0, 0, 0) )
 71     {
 72         if(msg.message == TALK_MESSAGE)
 73         {
 74             PostMessage (NULL, WM_QUIT, 0, 0);
 75         }
 76         DispatchMessage(&msg);
 77     }
 78 
 79     DWORD nThreadId = GetCurrentThreadId();
 80     g_nNum++;
 81     printf("线程编号为%d  全局资源值为%d
", nThreadId, g_nNum); 
 82     PostThreadMessage (nHandleThreadID[2], TALK_MESSAGE, 0, 0);
 83     
 84 
 85     return 0;
 86 }
 87 
 88 DWORD WINAPI Fun3 (LPVOID lpThreadParameter)
 89 {
 90     
 91     MSG msg;
 92     while( GetMessage(&msg, 0, 0, 0) )
 93     {
 94         if(msg.message == TALK_MESSAGE)
 95         {
 96             PostMessage (NULL, WM_QUIT, 0, 0);
 97         }
 98         DispatchMessage(&msg);
 99     }
100 
101     DWORD nThreadId = GetCurrentThreadId();
102     g_nNum++;
103     printf("线程编号为%d  全局资源值为%d
", nThreadId, g_nNum); 
104     PostThreadMessage (nHandleThreadID[3], TALK_MESSAGE, 0, 0);
105     
106     return 0;
107 }
108 
109 DWORD WINAPI Fun4 (LPVOID lpThreadParameter)
110 {
111     MSG msg;
112     while( GetMessage(&msg, 0, 0, 0) )
113     {
114         if(msg.message == TALK_MESSAGE)
115         {
116             PostMessage (NULL, WM_QUIT, 0, 0);
117         }
118         DispatchMessage(&msg);
119     }
120 
121     DWORD nThreadId = GetCurrentThreadId();
122     g_nNum++;
123     printf("线程编号为%d  全局资源值为%d
", nThreadId, g_nNum); 
124     PostThreadMessage (nHandleThreadID[4], TALK_MESSAGE, 0, 0);
125 
126     return 0;
127 }
128 
129 DWORD WINAPI Fun5 (LPVOID lpThreadParameter)
130 {
131     MSG msg;
132     while( GetMessage(&msg, 0, 0, 0) )
133     {
134         if(msg.message == TALK_MESSAGE)
135         {
136             PostMessage (NULL, WM_QUIT, 0, 0);
137         }
138         DispatchMessage(&msg);
139     }
140 
141     DWORD nThreadId = GetCurrentThreadId();
142     g_nNum++;
143     printf("线程编号为%d  全局资源值为%d
", nThreadId, g_nNum); 
144     //PostThreadMessage (nHandleThreadID[1], TALK_MESSAGE, 0, 0);
145 
146     return 0;
147 }

访问顺序为: Fun1完成通知Fun2,Fun2完成通知Fun3,Fun3完成通知Fun4,Fun4完成通知Fun5.

执行结果:

  线程编号为4740  全局资源值为1
线程编号为2484  全局资源值为2
线程编号为2408  全局资源值为3
线程编号为3564  全局资源值为4
线程编号为1460  全局资源值为5
请按任意键继续. . .

=================================

做到对共享内存区的同步访问。

注:加深理解互斥和同步技术,如果真的是需要实现同步时,最好还是用事件、信号量技术。

   

  

原文地址:https://www.cnblogs.com/xuxu8511/p/3145516.html