zoukankan      html  css  js  c++  java
  • 线程同步——用户模式下线程同步——Slim读写锁实现线程同步

      1 //Slim读/写锁实现线程同步
      2 SRWlock 的目的和关键段相同:对同一资源进行保护,不让其它线程访问。
      3 但是,与关键段不同的是,SRWlock允许我们区分哪些想要读取资源的线程(读取者线程)
      4 和哪些想要更新资源值的线程(写入者线程)。让所有读取者资源在同一时刻访问共享资源应该是
      5 可行的,这是因为仅仅读取资源并不存在破坏数据的风险。只有当写入者线程想要对资源进行更新时才需要同步。
      6 这种情况下,写入者线程应该独占资源访问权:任何线程,无论是读取还是写入者线程,都不许访问资源。
      7 这就是SRWlock强大之处。
      8 
      9 //使用步骤:
     10 //(1)必须先定义 CRITICAL_SECTION 结构
     11 SRWLOCK g_cs;
     12 //(2)初始化关键段 SRWLOCK
     13 InitializeSRWLock(&g_cs);
     14 //3)写入者线程
     15 DWORD WINAPI ThreadFunOne(PVOID pvParam) 
     16 {
     17     AcquireSRWLockExclusive(&g_cs)  ;
     18 
     19     //写入资源  应该放在AcquireSRWLockExclusive和ReleaseSRWLockExclusive函数之间
     20     g_x ++ ;
     21 
     22     ReleaseSRWLockExclusive(&g_cs);
     23     return 0;
     24 }
     25 //4)读取者线程
     26 DWORD WINAPI ThreadFunTwo(PVOID pvParam)
     27 {
     28     AcquireSRWLockShared(&g_cs)  ;
     29 
     30     //读取资  源应该放在AcquireSRWLockShared和ReleaseSRWLockShared函数之间
     31     cout<<"ThreadFunTwo:"<<g_x<<endl  ;
     32 
     33     ReleaseSRWLockShared(&g_cs);
     34     return 0;
     35 }
     36 
     37 不存在用来删除或者销毁 SRWLOCK 的函数,因为系统会自动执行清理工作
     38 
     39 与关键段相比,SRWlock 缺乏两个特性。
     40 1)不存在TryEnter(Shared/Exclusive)SRWLock之类的函数:如果锁已经被占用,
     41 那么调用AcquireSRWLock(Shared/Exclusive)会阻塞调用线程。
     42 2)不能递归的获得 SRWLOCK 也就是说一个线程不能多次写入资源而多次锁定资源,
     43 然后多次调用ReleaseSRWLock*来释放资源锁定。
     44 
     45 
     46 
     47 
     48 
     49 #include "windows.h"
     50 #include "iostream"
     51 using namespace std;
     52 long g_x = 0 ;
     53 //(1)必须先定义 CRITICAL_SECTION 结构
     54 SRWLOCK g_cs;
     55 
     56 //定义线程函数1
     57 DWORD WINAPI ThreadFunOne(PVOID pvParam) ;
     58 
     59 //定义线程函数2
     60 DWORD WINAPI ThreadFunTwo(PVOID pvParam);
     61 
     62 int main()
     63 {
     64 
     65     //(2)初始化关键段 SRWLOCK
     66     InitializeSRWLock(&g_cs);
     67 
     68     //创建线程1
     69     HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL);
     70     CloseHandle(hThreadOne);
     71 
     72     //创建线程2
     73     HANDLE hThreadTwo = CreateThread(NULL,0,ThreadFunTwo,0,0,NULL);
     74     CloseHandle(hThreadTwo);
     75 
     76     //让主线程先挂起,确保其它线程执行完成
     77     Sleep(1000); 
     78     cout<<g_x<<endl;
     79 
     80     //(4)清理CRITICAL_SECTION结构,必须确保已经没有资源使用此关键段,否则会出现不可预料的结果
     81     
     82     return 0 ;
     83 }
     84 
     85 DWORD WINAPI ThreadFunOne(PVOID pvParam) 
     86 {
     87     AcquireSRWLockExclusive(&g_cs)  ;
     88 
     89     //写入资源  应该放在AcquireSRWLockExclusive和ReleaseSRWLockExclusive函数之间
     90     g_x ++ ;
     91 
     92     ReleaseSRWLockExclusive(&g_cs);
     93     return 0;
     94 }
     95 
     96 DWORD WINAPI ThreadFunTwo(PVOID pvParam)
     97 {
     98     AcquireSRWLockShared(&g_cs)  ;
     99 
    100     //读取资  源应该放在AcquireSRWLockShared和ReleaseSRWLockShared函数之间
    101      cout<<"ThreadFunTwo:"<<g_x<<endl  ;
    102 
    103     ReleaseSRWLockShared(&g_cs);
    104     return 0;
    105 }
    106  
  • 相关阅读:
    【Prince2科普】Prince2七大主题之概论
    浅谈PRINCE2和PMP体系架构有何区别?
    Prince2是怎么考试的?
    Reporting Service服务SharePoint集成模式安装配置(3、4、安装sharepoint 2010必备组件及产品)
    Reporting Service服务SharePoint集成模式安装配置(1、虚拟机+ 2、AD域环境配置)
    DB2 添加license
    db2中临时表在存储过程中的使用
    DB2 函数快速构造测试数据
    db2 中 SQL判断物理表是否存在、修改表名
    DB2触发器简单例子
  • 原文地址:https://www.cnblogs.com/yfyzy/p/3916181.html
Copyright © 2011-2022 走看看