【Linux】读者写者模型

Dear 丶 2022-05-27 09:09 307阅读 0赞

前面我们已经学过了生产者消费者模型,那本文就来介绍一个与它有些相似却又不同的读者写者模型。

什么是读者写者模型?

  一个数据文件或记录可以被多个进程共享,我们把只要求读文件的进程称为Reader进程,其他进程则被称为Write进程。允许多个进程同时读一个共享对象,但是不允许一个Write进程和其他Reader进程或Writer进程同时访问对象。因为这样可能会造成混乱。所谓“读者写者问题”只是保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题。
  
总结一下,也是”321“原则:
三种关系
(1)写者与写者:不能两个人同时写,所以互斥
(2)读者与读者:可以两个人同时读,所以没有关系,也可以说是共享的
(3)写者与读者:一个文件不能又是被读,又是被写的,所以互斥;写完了才能读,不读了才开始写,所以说又是同步的。
两种角色:读者和写者。
一个读写场所。

读者写者模型的“321”原则,虽然与生产者消费者很类似,但是却又不同。消费者是将数据带拿走,而读者则只是读数据,数据还在,并没有被拿走。这是两者之间最大的不同。

读写锁

  有时候经常会出现公共资源修改的机会比较少,读资源的机会比较多的情况,此时,就需要用到我们的读写锁了。读写锁是一种特殊的自旋锁,能提高并发性。它允许多个多个读者来访问资源;写者是排他性的,一个读写锁同时只能有一个写者或多个读者,但不能同时既有读者又有写者。
  如果读写锁当前没有读者,也没有写者,那么写者可以立刻获得读写锁,否则它必须自旋在那,直到没有任何写者或读者;反过来,如果读写锁没有写者,那么读者就可以立刻得到读写锁,否则,它要自旋知道写者释放读写锁。

自旋锁

  自旋锁与互斥锁比较类似,都是为了解决资源的互斥问题。对于互斥锁来说,如果资源已经被占用,申请者只能挂起等待,直到被唤醒。自旋锁则不会被挂起,它会一直循环着看锁是否被释放。
  自旋锁适用于占用临界资源时间较短的时候,因为自旋锁不会引起调用者睡眠,所以自旋锁的效率高于互斥锁。但是由于自旋锁一直占用CPU,所以如果不能在短时间内获得锁,谁使用CPU效率下降。

注意:写独占,读共享,写锁的优先级高

读写锁的接口

初始化:

  1. int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
  2. const pthread_rwlockattr_t *restrict attr);

销毁:

  1. int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

加锁:

  1. int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//写锁
  2. int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//读锁

解锁:

  1. int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

下面我们写代码来使用一下读写锁,以加深印象。
这里使用线程来操作,创建三个写的线程,五个读的线程,这里写者优先级高。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<pthread.h>
  5. pthread_rwlock_t rwlock;
  6. int count = 0;
  7. void* route_write(void* arg)
  8. {
  9. int i = (int)arg;
  10. int t = 0;
  11. while(1)
  12. {
  13. t = count;
  14. usleep(10000);
  15. pthread_rwlock_wrlock(&rwlock);
  16. printf("(write)no:(%d), id=%x, t=%d, count=%d\n", i, pthread_self(), t, ++count);
  17. pthread_rwlock_unlock(&rwlock);
  18. usleep(90000);
  19. }
  20. }
  21. void* route_read(void* arg)
  22. {
  23. int i = (int)arg;
  24. while(1)
  25. {
  26. pthread_rwlock_rdlock(&rwlock);
  27. printf("(read)no:(%d), id=%x, count=%d\n", i, pthread_self(), count);
  28. pthread_rwlock_unlock(&rwlock);
  29. usleep(10000);
  30. }
  31. }
  32. int main()
  33. {
  34. pthread_t tid[8];
  35. pthread_rwlock_init(&rwlock, NULL);
  36. int i=0;
  37. for(; i<3; i++)
  38. {
  39. pthread_create(&tid[i], NULL, route_write, (void*)i);
  40. }
  41. for(i=3; i<8; i++)
  42. {
  43. pthread_create(tid+i, NULL, route_read, (void*)i);
  44. }
  45. for(i=0; i<8; i++)
  46. {
  47. pthread_join(tid[i], NULL);
  48. }
  49. pthread_rwlock_destroy(&rwlock);
  50. return 0;
  51. }

运行结果:可以发现读者出现的比较多,写者出现的比较少。
这里写图片描述
这里写图片描述

发表评论

表情:
评论列表 (有 0 条评论,307人围观)

还没有评论,来说两句吧...

相关阅读

    相关 读者--问题

    读者--写者问题 问题描述 问题分析 如何实现 总结 问题描述 有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共

    相关 Java并发之读者模型

    问题描述:设想一个飞机订票系统,其中有许多竞争的进程试图读写其中的数据。多个进程同时读取是可以接受的,但如果一个进程正在更新数据库,则所有的其他进程都不能访问数据库。即便是读操

    相关 读者_模型

    一.读者\_写者模型 我们知道在一些程序中存在读者写者问题,就是对某些资源的访问会存在两种可能的情况:一种就是写操作,写操作是可以独占资源的,也就是具有排他性;另一种情况

    相关 Linux读者模型

    前面我们已经学过了[生产者消费者模型][Link 1],那本文就来介绍一个与它有些相似却又不同的读者写者模型。 什么是读者写者模型?   一个数据文件或记录可以被多个进

    相关 linux 读者/自旋锁

    内核提供了一个自旋锁的读者/写者形式, 直接模仿我们在本章前面见到的读者/写者旗标. 这些锁允许任何数目的读者同时进入临界区, 但是写者必须是排他的存取. 读者写者锁有 一个类