码迷,mamicode.com
首页 > 编程语言 > 详细

第8章 用户模式下的线程同步(3)_Slim读写锁(SRWLock)

时间:2015-08-13 17:15:29      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

8.5 Slim读/写锁(SRWLock)——轻量级的读写锁

(1)SRWLock锁的目的

  ①允许读者线程同一时刻访问共享资源(因为不存在破坏数据的风险)

  ②写者线程应独占资源的访问权,任何其他线程(含写入的线程)要等这个写者线程访问完才能获得资源。

(2)SRWlock锁的使用方法

  ①初始化SRWLOCK结构体 InitializeSRWLock(PSRWLOCK pSRWLock);

  ②写者线程调用AcquireSRWLockExclusive(pSRWLock);以排它方式访问

     读者线程调用AcquireSRWLockShared以共享方式访问

  ③访问完毕后,写者线程调用ReleaseSRWLockExclusive解锁。读者线程要调用ReleaseSRWLockShared解锁

  ④注意SRWLock不需要删除和销毁,所以不用Delete之类的,系统会自动清理。

(3)SRWLock与临界区的不同

  ①不存在TryEnter(Shared/Exclusive)SRWLock之类的函数;如果锁己经被占用,那么调用AcquireSRWLock(Shared/Exclusive)会阻塞调用线程。(如排它写入时锁会被独占)

  ②不能递归获得SRWLock,即一个线程不能为了多次写入资源而多次锁定资源,再多次调用ReleaseSRWLock*来释放锁。

【SRWLock程序】

 技术分享

#include <windows.h>
#include <tchar.h>
#include <locale.h>
#include <time.h>

//////////////////////////////////////////////////////////////////////////
const int g_iThreadCnt = 20;
int g_iGlobalValue = 0;

//////////////////////////////////////////////////////////////////////////
SRWLOCK g_sl = { 0 };

//////////////////////////////////////////////////////////////////////////
DWORD WINAPI ReadThread(PVOID pParam);
DWORD WINAPI WriteThread(PVOID pParam);

//////////////////////////////////////////////////////////////////////////
int _tmain()
{
    _tsetlocale(LC_ALL, _T("chs"));

    srand((unsigned int)time(NULL));
    //读写锁只需初始化,不需要手动释放,系统会自行处理
    InitializeSRWLock(&g_sl);

    HANDLE aThread[g_iThreadCnt];
    DWORD  dwThreadId = 0;
    SYSTEM_INFO si = { 0 };
    GetSystemInfo(&si);

    for (int i = 0; i < g_iThreadCnt;i++){
        if (0 == rand()%2)
            aThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WriteThread, NULL,
                                      CREATE_SUSPENDED,&dwThreadId);
        else 
            aThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadThread, NULL,
                                     CREATE_SUSPENDED, &dwThreadId);
        SetThreadAffinityMask(aThread[i],1<<(i % si.dwNumberOfProcessors));
        ResumeThread(aThread[i]);
    }

    //等待所有线程结束
    WaitForMultipleObjects(g_iThreadCnt,aThread,TRUE,INFINITE);

    for (int i = 0; i < g_iThreadCnt;i++){
        CloseHandle(aThread[i]);
    }

    _tsystem(_T("PAUSE"));
    return 0;
}
////////////////////////////////////////////////////////////////////////////
////不加保护的读写
//DWORD WINAPI ReadThread(PVOID pParam)
//{
//    _tprintf(_T("Timestamp[%u]:Thread[ID:0x%x]读取全局变量值为%d\n"), 
//             GetTickCount(),GetCurrentThreadId(),g_iGlobalValue);
//    return 0;
//}
//
////////////////////////////////////////////////////////////////////////////
//DWORD WINAPI WriteThread(PVOID pParam)
//{
//
//    for (int i = 0; i <= 4321; i++){
//        g_iGlobalValue = i;
//        //模拟一个时间较长的处理过程
//        for (int j = 0; j < 1000; j++);
//    }
//
//    //我们的要求是写入的最后数值应该为4321,全局变量未被保护
//    //其中线程可能读取0-4321的中间值,这不是我们想要的结果!
//    _tprintf(_T("Timestamp[%u]:Thread[ID:0x%x]写入数据值为%d\n"),
//             GetTickCount(), GetCurrentThreadId(), g_iGlobalValue);
//    return 0;
//}

//////////////////////////////////////////////////////////////////////////
DWORD WINAPI ReadThread(PVOID pParam)
{
    //以共享的访问读
    __try{
        AcquireSRWLockShared(&g_sl);

        //读出来的全局变量要么是0,要么是4321。不可能有其他值
        //当读线程第1个被调度时,会读到0.但一旦写线程被调度,以后所有的
        //读取的值都会是4321
        _tprintf(_T("Timestamp[%u]:Thread[ID:0x%X]读取全局变量值为%d\n"),
                 GetTickCount(), GetCurrentThreadId(), g_iGlobalValue);
    }
    __finally{
        ReleaseSRWLockShared(&g_sl);
    }

    return 0;
}


//////////////////////////////////////////////////////////////////////////
DWORD WINAPI WriteThread(PVOID pParam)
{
    //写时以排它的方式
    __try{
        AcquireSRWLockExclusive(&g_sl);
        for (int i = 0; i <= 4321; i++){
            g_iGlobalValue = i;
            SwitchToThread(); //故意切换到其他线程,很明显
                              //在这个循环的期间,因排它方式
                              //所以其它访问锁的线程会被挂起
                              //从而无法读或写。
        }

        //我们的要求是写入的最后数值应该为4321,全局变量未被保护
        //其中线程可能读取0-4321的中间值,这不是我们想要的结果!
        _tprintf(_T("Timestamp[%u]:Thread[ID:0x%X]写入数据值为%d\n"),
                 GetTickCount(), GetCurrentThreadId(), g_iGlobalValue);
    }
    __finally{
        ReleaseSRWLockExclusive(&g_sl);
    }

    return 0;
}

(4)SRWLock锁与其他锁的比较

 

第8章 用户模式下的线程同步(3)_Slim读写锁(SRWLock)

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4727734.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!