C++读写锁特性说明

读写问题

假设某个数据对象是释若干进程共享的,这些进程的某些只会这种共享对象的内容,另一些则只会更新这种共享对象数据。

可以把这些进程分为两类,一类负责读取数据对象,称为读者进程,另一类负责更新共享数据,称为写者进程。多个读者可以同时获取共享对象,但是当一个写者和另外一个读者(或者写者)同时存取对象时,就会发生混乱

为了避免发生混乱现象,要求写者进程互斥地存取共享对象,这类同步问题就称为读写问题

读写锁

读写锁是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁,它是一种特殊的自旋锁。

读写锁是用于解决类读写问题,比如有些公共数据修改的机会很少,但其读的机会很多。并且在读的过程中会伴随着查找,给这种代码加锁会降低我们的程序效率,读写锁可以解决此类问题;其中读操作可并发重入,而写操作是互斥的。

优先级策略

根据不同的优先级策略,可以将读写锁分为以下两种:

  • 读者优先:允许最大并发,但写操作可能饿死。
  • 写者优先:一旦所有已经开始的读操作完成,等待的写操作立即获得锁。

读者优先策略

除非有写者在写文件,否则没有一个读者需要等待。

分析思想:

读者到:
1)无读者、写者,新读者可以读
2)有写者等,但有其它读者正在读,则新读者也可以读
3)有写者写,新读者等

写者到:
1)无读者,新写者可以写
2)有读者,新写者等待
3)有其它写者,新写者等待

写者优先策略

一旦一个写者到来,它应该尽快对文件进行写操作。则新来到的读者不允许进行读操作。

分析思想:

读者到:
1)  无读者且无写者,新读者读
2)  有读者但无写者等待,新读者读
3)  有读者但有写着等待,读者等待
4)  有写者在写,新读者等待

写者到:	
1)  无读者且无写者,新写者写
2)  有读者在读,新写者等待
3)  有写者写,新写者等待
Windows系统读写锁

读写锁(Slim reader/writer,SRW lock)用于进程内的线程间同步。 SRW既不是公平的也不是先进先出的。SRW锁提供两种读取模式,访问共享资源 :

共享模式,它允许多个读取线程对共享资源进行只读访问,从而使它们能够同时从共享资源中读取数据。

独占模式,它授予对一个写入线程的一次读/写访问权限。在独占模式下获取锁定后,在写者线程释放锁定之前,其他任何线程都无法访问该共享资源。

相关API
在这里插入图片描述
实例:

int         g_test_data = 0;
SRWLOCK     g_srwLock;
const int MAX_RAND_TIME = 10;
const int MAX_RADN_DATA = 1000;

void reader(int id)
{
    int rand_time = rand() % MAX_RAND_TIME;
    //线程安全型打印
    CStdPrinter::PrintMsg("reader thread(%d)  read begin....\n", id);

    std::this_thread::sleep_for(std::chrono::milliseconds(rand_time * 300));

    CStdPrinter::PrintMsg("reader thread(%d)  read end (data : %d)....\n", id, g_test_data);
}

void writer(int nID)
{
    int rand_time = rand() % MAX_RAND_TIME;

    CStdPrinter::PrintMsg("\t writer thread (%d) writer data  begin....\n", nID);
    g_test_data = (rand()* nID) % 1000;
    std::this_thread::sleep_for(std::chrono::milliseconds(rand_time * 300));
    CStdPrinter::PrintMsg("\t writer thread (%d) writer data (data: (%d)  end....\n", nID, g_test_data);
}

//读者线程
void  win_reader_thread(int nID)
{
    while (1)
    {
        CStdPrinter::PrintMsg("读者线程(%d)进入等待状态...\n", nID);
        AcquireSRWLockShared(&g_srwLock);
        reader(nID);
        ReleaseSRWLockShared(&g_srwLock);

        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

//写者线程
void  win_writer_thread(int nID)
{
    while (1)
    {
        CStdPrinter::PrintMsg("写者线程(%d)进入等待状态....\n", nID);
        AcquireSRWLockExclusive(&g_srwLock);
        writer(nID);
        ReleaseSRWLockExclusive(&g_srwLock);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

//读写锁测试代码
void  SRW_lock_instance()
{
    const int  READER_NUM = 5;
    const int  WRITER_NUM = 1;

    InitializeSRWLock(&g_srwLock);//自动析构

    std::thread arrThread[READER_NUM];
    std::thread arrWriterThread[WRITER_NUM];

    for (int i = 0; i < READER_NUM; i++)
    {
        arrThread[i] = std::thread(win_reader_thread, i + 1);
    }

    for (int i = 0; i < WRITER_NUM; i++)
    {
        arrWriterThread[i] = std::thread(win_writer_thread, i + 1);
    }

    for (int i = 0; i < WRITER_NUM; i++)
    {
        arrWriterThread[i].join();
    }

    for (int i = 0; i < READER_NUM; i++)
    {
        arrThread[i].join();
    }
}

运行结果:

读者线程(1)进入等待状态...
reader thread(1)  read begin....
读者线程(2)进入等待状态...
读者线程(3)进入等待状态...
reader thread(2)  read begin....
读者线程(4)进入等待状态...
reader thread(3)  read begin....
读者线程(5)进入等待状态...
reader thread(4)  read begin....
写者线程(1)进入等待状态....
reader thread(5)  read begin....
reader thread(1)  read end (data : 0)....
reader thread(2)  read end (data : 0)....
reader thread(3)  read end (data : 0)....
reader thread(4)  read end (data : 0)....
reader thread(5)  read end (data : 0)....
         writer thread (1) writer data  begin....
         writer thread (1) writer data (data: (467)  end....
读者线程(2)进入等待状态...
读者线程(1)进入等待状态...
reader thread(2)  read begin....
读者线程(3)进入等待状态...
reader thread(1)  read begin....
读者线程(4)进入等待状态...
reader thread(3)  read begin....
读者线程(5)进入等待状态...
reader thread(4)  read begin....
reader thread(5)  read begin....
写者线程(1)进入等待状态....
reader thread(2)  read end (data : 467)....
reader thread(1)  read end (data : 467)....
reader thread(3)  read end (data : 467)....
reader thread(4)  read end (data : 467)....
reader thread(5)  read end (data : 467)....
         writer thread (1) writer data  begin....
读者线程(2)进入等待状态...
读者线程(1)进入等待状态...
读者线程(3)进入等待状态...
读者线程(4)进入等待状态...
读者线程(5)进入等待状态...
^C请按任意键继续. . .

参考资料:

https://blog.csdn.net/lwfcgz/article/details/8091242
https://blog.csdn.net/SpadgerZ/article/details/53045724
https://docs.microsoft.com/en-us/windows/desktop/sync/slim-reader-writer--srw--locks

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值