zoukankan      html  css  js  c++  java
  • 浅尝《Windows核心编程》之线程用户级同步

    线程用户级同步有多种方法,包括了互锁和关键区等。这里将重点介绍如何使用关键区的方法来实现线程在线程级的同步。

    1.对关键区的使用

    //声明一个关键区域变量
    CRITICAL_SECTION cs;

    //在使用之前一定要初始化,否则会出现“不可预见性”错误
    ::InitializeCriticalSection(&cs);

    //在需要的地方进行使用
    ::EnterCriticalSection(&cs);
    //使用到了需要做到保护的资源
    //
    ::LeaveCriticalSection(&cs));

    //用完之后需要销毁
    ::DeleteCriticalSection(&cs);

    2. 注意点:

    (1)关键区域只是对资源的锁住,并不是说锁住其它的线程。具体来说,当线程1用到了资源a,并且使用了关键区域,在它得到许可进入到关键区域中后,他仍然存在几率被置换出可调用线程,进入等待线程,这是如果线程2运行到了有相同关键区域变量的EnterCriticalSection语句,那么线程2就会被置换为等待状态(就算它还剩有时间片),直到线程1离开了关键区域。

    (2)对CRITICAL_SECTION结构,当拥有一项可供多个线程访问的“资源”时,就应该创建一个CRITICAL_SECTION结构变量,即如果线程1和线程2访问一个资源,而线程1和线程3访问另外一个资源,那么应该为每一个资源创建一个CRITICAL_SECTION结构变量。但是当有多个资源总是被一起使用,就可以创建一个CRITICAL_SECTION结构变量。

    (3)编写的需要是哦那个共享资源的任何代码都必须封装在EnterCriticalSection和LeaveCriticalSection里。

     (4)EnterCriticalSection 和LeaveCriticalSection 工作原理。

    前者只是做了一系列的测试,并且以绝对的原子性完成所有的测试。若资源没有被使用,就立即返回并且继续调用它的线程,否则就让此调用线程在此语句上进入等待,计数器加1,以指明调用之线程多少次被赋予对共享资源的访问权。

    后者每次计数时要递减1。如果计数器等于0,就查看在调用EnterCriticalSection者中是否有别的线程正在等待,如果至少有一个线程正在等待,它就更新成员变量,并且使等待线程中的一个线程再次被激活为可调度。如果没有正在等待的线程,它就更新成员变量,以指明没有线程正在访问该资源。

    3.关键区域和循环锁

    应该尽可能地将循环锁用于关键区域。如果使用了循环锁,EnterCriticalSection 被调用时,它就使用了循环锁进行循环,以便设法多次取得该资源。只有当为了取得资源的每次试图都失败的情况下,该线程才转入内核方式(这个转换时由于“Active线程”->“等待线程”状态导致的,非常耗时,也是尽量使用循环锁的原因。)以便进入等待状态。

     使用方法,只要将InitializeCriticalSection 改为 InitializeCriticalSectionAndSpinCount 。注意这个函数的第二参数,是循环的次数,作为一个指导性的原则,保护对进程的堆进行访问的关键区域使用循环此时为4000次。 可以使用SetCriticalSecionSpinCount改变循环次数。

    4.对使用关键代码段的提示与技巧

    (1)每一个共享资源使用一个CRITICAL_SECTION变量。

    如果应用程序中拥有若干个互不相干的数据结构,应该为每一个数据结构创建一个CRITICAL_SECTION.

     (2)必须始终按照完全相同的顺序请求对资源的访问

    同时访问多个资源时,必须始终按照完全相同的顺序请求资源的访问,比如当线程1有

    EnterCriticalSection(&cs1);
    EnterCriticalSection(
    &cs2);
    //.            
    LeaveCriticalSection(&cs1);
    LeaveCriticalSection(
    &cs1);

    如果线程2也要使用到cs1和cs2,那么他的关键区域进入点的测试顺序要与其他使用cs1和cs2的完全一致,否则就会出现死锁现象。

    但调用LeaveCriticalSection函数时,按照什么顺序访问资源没有关系,因为该函数绝不会使线程进入等待状态。

     

    (3)不要长时间运行关键代码段

  • 相关阅读:
    Linux文件权限学习总结
    【转】Hibernate和ibatis的比较
    Spring AOP原理及拦截器
    Spring AOP (下)
    Spring AOP (上)
    SQL语句限定查询知识点总结
    多线程知识点总结
    关于tomcat那些事情
    java.lang.NoClassDefFoundError: org/apache/commons/codec/DecoderException 的解决办法
    cacti 与 nagios 一些总结 【八】
  • 原文地址:https://www.cnblogs.com/aicro/p/1497373.html
Copyright © 2011-2022 走看看