• core--线程同步(用户模式)


    用户模式下的多线程同步只适用用于同一个进程内的多个线程,其范围使用于读写问题:比如一本书,必须是作者A写完之后,读者B才能够读取。否则作者一边修改,读者一边读,完全乱套。

    线程读者B如何能在多线程环境下完成等待呢?请参看这里

    那要等到什么时候呢?

    LONG InterlockedExchange(    //该函数将target变量的值

        LPLONG Target,    // 指向32位需要改变的变量的地址
              LONG Value          // 新值
              );                          // 返回target变量的旧值

    bool globeResource=False;

    如果在多个线程中都调用如下代码,就能完成等待的效果

    while(InterLockedExchange(globeResource,True))

        Sleep(0);

    //此处线程的其他真正任务代码

    InterLockedExchange(globeResource,Flase)

    “假如1个线程正在试用该值的话,那么globeResource就为true,当另外一个线程也开始执行,interlockedexchange函数就会返回true,从而进入sleep(0),也就是放弃该线程的时间片,立即切换到其他线程。当操作系统下一次调用,函数依然返回ture,依然sleep(0),这就是说线程一直都不继续执行下面的代码,从而完成了等待的效果,当第一个线程完成代码之后,globeResource就为false,那么第二个线程就会推出while循环,执行线程其他的代码。”

    InterlockedExchange函数其实是windows原子访问家族中的一个。

    什么是原子访问?请看下面代码:

    int a=0;

    a++;

    这里的a++虽然只有一句话,但是在cpu级别会被解释为三句话;

    mov eax,[a]

    add eax

    mov [a],eax

    要保证这种加法是原子操作,也就是一部到位就要是用windows原子访问家族

    windows原子访问家族

    LONG InterlockedExchangeAdd (

    PLONG Addend,    // 指向需要被加的变量

    LONG Increment    // increment value
          );

    InterlockedExchangpointer

    PVOID InterlockedCompareExchange(

    PVOID *Destination,    // pointer to the destination pointer
          PVOID Exchange,    // the exchange value
          PVOID Comperand    // the value to compare
          );

    更加优秀的同步

    查看上面的代码,可以发现线程总是在执行,总是处于可调度状态,而不是等待状态:虽然是通过调用sleep来完成的等待,但是while循环在每次系统调用之后会执行一次,有没有直接让线程处于不可调度状态,并在等到响应的资源过后就然线程处于可调度状态呢?请看下面的例子

    LPCRITICAL_SECTION g_cs;//进程全局变量

    int index=0;

    线程:

    EnterCriticalSection(&g_cs);

    index++;//在这里执行一大段需要同步的代码

    LeaveCriticalSection(&g_cs)

    VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection // 指向资源的指针 );

    VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection // 指向资源的指针 );

    通过上面的这对函数,就能够完成然线程进入等待状态,在其他线程释放g_cs之后,自动然线程变成可调度状态。但是在使用的时候一定要确保这两个函数成对出现,否则就像你进入厕所,不离开一样,别人就永远进不了!

    EnterCriticalSection函数会让线程等待   

    TryEnterCriticalSection函数不会让线程等待,如果其他线程正在使用,那么函数就将直接返回false,否则返回True

    当线程进入等待状态之后,也就是说线程从用户状态切换到内核状态了,这个切换会用掉cpu大概1000多个时钟周期,也就是说非常耗费系统,为了不进入内核状态,可以使用

    initializecriticalsectionandspincount(&g_cs,spinCount) spinCount表示循环次数,相当于上面的wihle循环多少次

  • 相关阅读:
    ubuntu18安装net-snmp
    virtual box安装ubuntu系统 ping通 && xshell可以连接
    高中操场所见所思
    如何写好研究生开题报告
    在加州考驾照
    一个软件工程项目竞赛网站
    结对项目总结
    喜马拉雅随车听开通啦
    裘老师赠书
    推荐博客链接
  • 原文地址:https://www.cnblogs.com/pavkoo/p/3413166.html
Copyright © 2020-2023  润新知