zoukankan      html  css  js  c++  java
  • 同步与互斥

    如果是问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
    请按任意键继续. . .

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

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

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

       

      

  • 相关阅读:
    系统重启
    Linux驱动程序开发
    Linux 下实现控制屏幕显示信息和光标的状态
    Linux C 语言 获取系统时间信息
    linux 获取系统屏幕分辨率
    Linux下得到显示屏参数的方法
    Linux如何关闭防火墙和查看防火墙的具体情况
    查看Linux下网卡状态或 是否连接(转)
    ArcGIS Engine中正确释放打开资源
    在ArcEngine下实现图层属性过滤的两种方法
  • 原文地址:https://www.cnblogs.com/xuxu8511/p/3145516.html
Copyright © 2011-2022 走看看