读者_写者模型

短命女 2022-07-12 13:15 336阅读 0赞

一.读者_写者模型

我们知道在一些程序中存在读者写者问题,就是对某些资源的访问会存在两种可能的情况:一种就是写操作,写操作是可以独占资源的,也就是具有排他性;另一种情况就是读操作,在读操作中可以有多个资源并发的去访问某种资源,它的访问方式是共享的。这种模型是从对文件的读写操作中总结出的一种模型。

1.在读者和写者的这种模型中,存在3种关系,他们是:

1).读者和读者之间,读者与读者之间是可以并发的访问某种资源的,所以他们之间是没有关系的。

2).读者和写者之间,我们知道对一个文件来说是不可以既读又写的,可能会导致数据的二义性问题。读者和写着之间是互斥和同步的关系。

3).写着和写着之间,存在互斥的关系。

2.在上面描述读者写者关系中提到了互斥和同步,那仫为什仫要保证互斥和同步的关系呢?

互斥:指某一种资源某一时刻只能允许一个访问者对它进行访问,具有唯一性和排他性。但是资源的互斥是无法保证访问者对资源的访问顺序的,即如果有多个访问者访问该资源时,访问是无顺序的。

同步:同步是在互斥的基础上(大多数是互斥+同步,有的情况下只需要同步),通过一些机制实现访问者对资源的有序访问

理解了互斥和同步让我们继续来看读者和写者问题,我们知道读者在读的过程中存在查找操作,费时较长,如果给读者加锁会降低这种模型的实现效率,可以总结为读者写者模型就是一种多读少写的情况,为了解决这种情况,引入了读者锁的概念。

二.读写锁

读写锁是一种特殊的自旋锁,一个读写锁同时只能有一个写着或者是多个读者,但是不能同时即有读者又有写者,由上述读者和写者的关系可得。读写锁相对互斥锁来说,可以允许多个线程同时占用读模式的读写锁,具有更高的试用性和并行性。

关于读写锁的几个常见的函数:

1).创建读写锁,读写锁的类型是pthread_rwlock_t,创建的格式为:pthread_rwlock_t myrwlock。

2).创建之后就要初始化,读写锁的初始化函数为:

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

成功返回0,失败返回错误码。attr表示读写锁的属性,一般设置为NULL表示默认.

3).创建之后就需要销毁该读写锁,销毁函数为:

  1. int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

成功返回0,失败返回操作码,rwlock就是你定义的读写锁.

4).读者加锁函数

  1. int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  2. int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

pthread_rwlock_rdlock和pthread_rwlock_tryrdlock的区别:

对读者进行加锁,pthread_rwlock_rdlock如果加锁失败则该线程就会被挂起等待;如果某些线程在加锁失败之后不想被挂起,则可以使用pthread_rwlock_trylock

6).写者加锁函数

  1. int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
  2. int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

成功返回0,失败返回错误码,两者的区别类似读者加锁函数

7).有加锁必然存在解锁函数,不管是读者解锁还是写着解锁都是pthread_rwlock_unlock函数。

  1. int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

成功返回0,失败返回错误码。

三.自旋锁
上述提到的读写锁就是自旋锁的一种,那仫什仫是自旋锁呢?它是为实现保护共享资源而提出的一种锁机制,自旋锁和互斥锁都是为了解决对某种资源的互斥使用,在任意一个时刻只能有一个访问者访问该资源。读写锁虽然是自旋锁的一种特殊情况,两者还是存在区别的:两者在调度机制上存在不同。如果资源已经被占用,使用互斥锁的申请者就会进入休眠状态,而自旋锁的申请者就会被其他执行单元保持,调用者会一直查看该锁的保持者是否已经释放该锁了,所以这种机制的锁就叫自旋锁。

自旋锁的效率远远高于互斥锁,因为自旋锁不会引起访问者的休眠,减少了保持数据的开销,虽然自旋锁的效率比较高,但是它也存在一些问题:

1).降低CPU的使用效率。试想一下如果访问者一直未得到锁,那仫它就会一直在CPU中等待该锁被释放,如果是单核操作系统这种弊端就会更加明显了。

2).可能会造成死锁。当递归调用或者调用一些函数时可能造成死锁,比如调用copy_to_user(),copy_from_user(),kmalloc()。

所以虽然自旋锁比较高效,但是要恰当使用,在多CPU或者是内核可抢占,SMP的情况下才需要自旋锁,自旋锁使用保持锁时间比较短的情况下.

四.一个简单的实现多读者一个写着的读写者模型

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. int count=0;
  4. pthread_rwlock_t myrwlock;
  5. void *reader_run(void *arg)
  6. {
  7. while(1)
  8. {
  9. sleep(1);
  10. int ret=pthread_rwlock_rdlock(&myrwlock);
  11. if(ret != 0)
  12. {
  13. printf("the lock is user by writer\n");
  14. continue;
  15. }
  16. printf("reader is %lu,count=%d\n",pthread_self(),count);
  17. pthread_rwlock_unlock(&myrwlock);
  18. }
  19. }
  20. void *writer_run(void *arg)
  21. {
  22. while(1)
  23. {
  24. sleep(1);
  25. int ret=pthread_rwlock_wrlock(&myrwlock);
  26. if(ret != 0)
  27. {
  28. printf("the lock is used by reader\n");
  29. continue;
  30. }
  31. count++;
  32. printf("writer is %lu,count=%d\n",pthread_self(),count);
  33. pthread_rwlock_unlock(&myrwlock);
  34. }
  35. }
  36. int main()
  37. {
  38. pthread_rwlock_init(&myrwlock,NULL);
  39. pthread_t reader;
  40. pthread_t writer;
  41. pthread_create(&reader,NULL,reader_run,NULL);
  42. pthread_create(&writer,NULL,writer_run,NULL);
  43. pthread_join(reader,NULL);
  44. pthread_join(writer,NULL);
  45. pthread_rwlock_destroy(&myrwlock);
  46. return 0;
  47. }

它的现象是:

Center

在这里就分享结束了~~~~

发表评论

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

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

相关阅读

    相关 读者--问题

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

    相关 Java并发之读者模型

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

    相关 读者_模型

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

    相关 【Linux】读者模型

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