您的位置:首页 > 其它

读者_写者模型

2017-02-24 13:23 246 查看
 一.读者_写者模型

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

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

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

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

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

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

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

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

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

二.读写锁

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

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

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

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

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


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

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

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);


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

   4).读者加锁函数

   

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);


 pthread_rwlock_rdlock和pthread_rwlock_tryrdlock的区别:

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

   6).写者加锁函数

    

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);


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

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

    

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);


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

 三.自旋锁

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

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

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

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

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

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

   

#include<stdio.h>
#include<pthread.h>

int count=0;
pthread_rwlock_t myrwlock;

void *reader_run(void *arg)
{
while(1)
{
sleep(1);
int ret=pthread_rwlock_rdlock(&myrwlock);
if(ret != 0)
{
printf("the lock is user by writer\n");
continue;
}
printf("reader is %lu,count=%d\n",pthread_self(),count);
pthread_rwlock_unlock(&myrwlock);
}
}

void *writer_run(void *arg)
{
while(1)
{
sleep(1);
int ret=pthread_rwlock_wrlock(&myrwlock);
if(ret != 0)
{
printf("the lock is used by reader\n");
continue;
}
count++;
printf("writer is %lu,count=%d\n",pthread_self(),count);
pthread_rwlock_unlock(&myrwlock);
}
}

int main()
{
pthread_rwlock_init(&myrwlock,NULL);
pthread_t reader;
pthread_t writer;
pthread_create(&reader,NULL,reader_run,NULL);
pthread_create(&writer,NULL,writer_run,NULL);
pthread_join(reader,NULL);
pthread_join(writer,NULL);
pthread_rwlock_destroy(&myrwlock);
return 0;
}


   它的现象是:

   


   

   在这里就分享结束了~~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息