在《秒杀多线程第十一篇读者写者问题》文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题。问题虽然得到了解决,但代码有点复杂。本篇将介绍一种新方法——读写锁SRWLock来解决这一问题。读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程)。对于读取者线程,读写锁会允许他们并发的执行。当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待。因此用读写锁来解决读者写者问题会使代码非常清晰和简洁。

下面就来看看如何使用读写锁,要注意编译读写锁程序需要VS2008,运行读写锁程序要在Vista或Windows Server2008系统(比这两个更高级的系统也可以)。读写锁的主要函数就五个,分为初始化函数,写入者线程申请和释放函数,读取者线程申请和释放函数,以下是详细的函数使用说明:

第一个 InitializeSRWLock

函数功能:初始化读写锁

函数原型:VOID InitializeSRWLock(PSRWLOCK SRWLock);

函数说明:初始化(没有删除或销毁SRWLOCK的函数,系统会自动清理)

第二个 AcquireSRWLockExclusive

函数功能:写入者线程申请写资源。

函数原型:VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);

第三个 ReleaseSRWLockExclusive

函数功能:写入者线程写资源完毕,释放对资源的占用。

函数原型:VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);

第四个 AcquireSRWLockShared

函数功能:读取者线程申请读资源。

函数原型:VOID AcquireSRWLockShared(PSRWLOCK SRWLock);

第五个 ReleaseSRWLockShared

函数功能:读取者线程结束读取资源,释放对资源的占用。

函数原型:VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);

注意一个线程仅能锁定资源一次,不能多次锁定资源。

使用读写锁精简后的代码如下(代码中变参函数的实现请参阅《C,C++中使用可变参数》,控制台颜色设置请参阅《VC 控制台颜色设置》):

  1. #include<stdio.h>
    #include<process.h>
    #include<Windows.h>
    /*按照逻辑,即使是读文件线程先运行,也要一直阻塞到第一个写线程执行完(因为写线程不运行,就没有数据。此时,读线程的执行就没有意义)。*/

    //设置控制台颜色输出
    BOOL SetConsoleColor(WORD wAttributes)
    {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hConsole == INVALID_HANDLE_VALUE)
    return false;
    return SetConsoleTextAttribute(hConsole, wAttributes);
    }

    const int READER_NUM = 5;

    CRITICAL_SECTION g_cs;
    SRWLOCK g_srwLock;

    //读者线程输出函数(变参函数的实现)
    void ReaderPrintf(char *pszFormat, ...)
    {
    va_list pArgList;
    va_start(pArgList, pszFormat);
    EnterCriticalSection(&g_cs);
    vfprintf(stdout, pszFormat, pArgList);
    LeaveCriticalSection(&g_cs);
    va_end(pArgList);
    }
    //读者线程函数
    unsigned int _stdcall ReaderThreadFun(PVOID pM)
    {
    ReaderPrintf(" 编号为%d的读者进入等待中...\n");
    //读者申请读取文件
    AcquireSRWLockShared(&g_srwLock);

    //读取文件
    ReaderPrintf("编号为%d的读者开始读取文件...\n");
    Sleep(rand() % 100);
    ReaderPrintf("编号为%d的读者结束读取文件!\n");

    ReleaseSRWLockShared(&g_srwLock);
    return 0;
    }

    void WriterPrintf(char *pszStr)
    {
    EnterCriticalSection(&g_cs);
    SetConsoleColor(FOREGROUND_GREEN);
    printf(" %s\n", pszStr);
    SetConsoleColor(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
    LeaveCriticalSection(&g_cs);
    }
    //写者函数
    unsigned int _stdcall WriterThreadFun(PVOID pM)
    {
    WriterPrintf("写者等待写文件...\n");
    //写者申请写文件
    AcquireSRWLockExclusive(&g_srwLock);

    WriterPrintf("写者正在写文件...\n");

    Sleep(rand() % 100);

    WriterPrintf("写者写文件完成!\n");

    ReleaseSRWLockExclusive(&g_srwLock);

    return 0;
    }

    int main()
    {
    printf("读者写者问题续 读写锁SRWLock\n");
    printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");

    InitializeCriticalSection(&g_cs);
    InitializeSRWLock(&g_srwLock);

    HANDLE hThread[READER_NUM + 1];
    int i;
    for (i = 1; i <= 2; i++)
    hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFun, NULL, 0, NULL);
    hThread[0] = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFun, NULL, 0, NULL);
    for (; i <= READER_NUM; i++)
    hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFun, NULL, 0, NULL);
    WaitForMultipleObjects(READER_NUM + 1, hThread, TRUE, INFINITE);

    for (i = 0; i < READER_NUM + 1; i++)
    CloseHandle(hThread[i]);

    DeleteCriticalSection(&g_cs);

    system("pause");
    return 0;
    }

对比下《秒杀多线程第十一篇读者写者问题》中的代码就可以发现这份代码确实清爽许多了。这个程序用VS2008编译可以通过,但在XP系统下运行会导致报错。

在Win7系统下能够正确的运行,结果如图所示:

最后总结一下读写锁SRWLock

1.读写锁声明后要初始化,但不用销毁,系统会自动清理读写锁。

2.读取者和写入者分别调用不同的申请函数和释放函数。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7650574

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

读者写者问题继 读写锁SRWLock的更多相关文章

  1. 多线程面试题系列(14):读者写者问题继 读写锁SRWLock

    在第十一篇文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一问题.读写锁在对资源进行保护的同时,还 ...

  2. 转---秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...

  3. 秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock (续)

    java 包实现了读写锁的操作: package com.multithread.readwritelock; import java.util.concurrent.CountDownLatch; ...

  4. 多线程 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...

  5. 读写锁 SRWLOCK

    读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程). 对于读取者线程,读写锁会允许他们并发的执行.当有写入者线程在占有资源时,读写锁会让其它写入 ...

  6. 最新Windows下c++读写锁SRWLock介绍

    https://blog.csdn.net/MoreWindows/article/details/7650574 https://blog.csdn.net/chenzhjlf/article/de ...

  7. 读者写者问题(有bug 后续更改)

    与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文 ...

  8. sqlite3 读写锁

    转载:https://blog.csdn.net/u012218838/article/details/79362929(sqlite3 使用读写锁SRWLOCK例子) 转载:https://my.o ...

  9. Linux多线程实践(6) --Posix读写锁解决读者写者问题

    Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *rest ...

随机推荐

  1. [html] 前端角度出发做好SEO需要考虑什么

    Meta标签优化 主要包括主题(Title),网站描述(Description),和关键词(Keywords).还有一些其它的隐藏文字比如Author(作者),Category(目录),Languag ...

  2. html5常用API之Full Screen

    所谓Full Screen API,就是全屏API,在html5中,该API允许开发者以编程方式将Web应用程序全屏运行,使Web应用程序更像本地应用程序.这款API十分简单有用,是html5初学者必 ...

  3. Windows不重启就使环境变量修改生效

    以修改环境变量“PATH”为例,修改完成后,进入DOS命令提示符,输入:set PATH=C: ,关闭DOS窗口.再次打开DOS窗口,输入:echo %PATH% ,可以发现“我的电脑”->“属 ...

  4. 测序原理 - PacBio技术资料

    手头有一套完整的PacBio技术资料,会慢慢的总结到博客上. 写在前面:PacBio公司主要有两个测序平台一个是RS,一个是最新的Sequel,下面如果没有指明则是在讲RS平台. SMRT测序技术总览 ...

  5. 线性表 - 从零开始实现by C++

    参考链接:数据结构探险之线性表篇     线性表

  6. 能源项目xml文件 -- springMVC-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  7. jmeter 构建一个LDAP测试计划

    添加用户 第一步你想做的每一个JMeter测试计划是添加一个线程组元素. 线程组告诉JMeter的用户数量你想模拟,用户应该发送的次数 请求,他们应该发送的请求的数量. 继续添加ThreadGroup ...

  8. 第二周 WBS、NABCD查阅

    WBS WBS:工作分解结构(Work Breakdown Structure) 创建WBS:创建WBS是把项目可交付成果和项目工作分解成较小的,更易于管理的组成部分的过程. WBS是项目管理重要的专 ...

  9. 51nod 1065 最小正子段和

    题目链接:51nod 1065 最小正子段和 房教说用前缀和做,然后看了别人博客懂了后就感觉,这个真有意思... #include<cstdio> #include<cstring& ...

  10. 20145236 《Java程序设计》第八周学习总结

    20145236 <Java程序设计>第八周学习总结 教材学习内容总结 第十四章 NIO与NIO2 认识NIO NIO使用频道(Channel)来衔接数据节点,在处理数据时,NIO可以让你 ...