您的位置:首页 > 运维架构 > Linux

读写锁解决读者与写者问题

2017-04-12 12:50 197 查看
读写锁是用来解决读者写者问题的,读操作可以共享,写操作是排他的,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读。

在编写多线程的时候,有一种情况是比较常见的。那就是,有些公共数据修改的机会比较少。相较改写,它们读的机会反而多的多。

读者写者模式:三种关系,两类人,一个场所

三种关系:

    读者与读者:无关系

    写者与写者:互斥

    读者与写者:同步与互斥

两类人:读者,写者

一个场所:同一临界资源(数据)

自旋锁:如果所等待条件不满足,不挂起,一直申请锁。适宜某个线程占用锁时间较短。读写锁就是一种自旋锁,在用户看来表现的是阻塞式等待,但是操作系统采用的是轮询等待,直到申请到锁,互斥锁在用户看来表现的也是阻塞式等待,但是操作系统采用的是挂起等待,直到申请锁。

当不断有多个读者准备读时,如果有写者到来,此时应该让当前读者读完后,提高写者优先级,下个进入临界区的是写者。---------写者优先,否则会造成写者饥饿

当不断有多个写者准备写时,如果有读者到来,此时应该让当前写者写完后,提高读者优先级,下个进入临界区的是读者。---------读者优先,否则会造成读者饥饿

读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:
1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
2.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行加锁的线程将会被阻塞
3.当读写锁在读模式的锁状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁的请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求则长期阻塞。

 读写锁最适用于对数据结构的读操作次数多于写操作的场合,因为,读模式锁定时可以共享,而写模式锁定时只能某个线程独占资源,因而,读写锁也可以叫做个共享-独占锁。

读写锁的操作:
头文件:#include<pthread.h>
读写锁的初始化:
定义读写锁: pthread_rwlock_t m_rw_lock;
函数原型: pthread_rwlock_init(pthread_rwlock_t * ,pthread_rwattr_t *);
返回值:0,表示成功,非0为一错误码,函数第二个参数一般是NULL,采用系统默认的属性
读写锁的销毁:
函数原型: pthread_rwlock_destroy(pthread_rwlock_t* );
返回值:0,表示成功,非0表示错误码
获取读写锁的读锁操作:分为阻塞式获取和非阻塞式获取,如果读写锁由一个写者持有,则读线程会阻塞直至写入者释放读写锁。(读者优先)
阻塞式:
函数原型:pthread_rwlock_rdlock(pthread_rwlock_t*);
非阻塞式:
函数原型:pthread_rwlock_tryrdlock(pthread_rwlock_t*);
返回值: 0,表示成功,非0表示错误码,非阻塞会返回ebusy而不会让线程等待
获取读写锁的写锁操作:分为阻塞和非阻塞,如果对应的读写锁被其它写者持有,或者读写锁被读者持有,该线程都会阻塞等待。(写者优先)
阻塞式:
函数原型:pthread_rwlock_wrlock(pthread_rwlock_t*);
非阻塞式:
函数原型:pthread_rwlock_trywrlock(pthread_rwlock_t*);
返回值: 0,表示成功
释放读写锁:
函数原型:pthread_rwlock_unlock(pthread_rwlock_t*);

注意:读锁和写锁最后都采用同一个释放锁的函数

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

int buf = 0;  //buf全局变量就是临界资源。
pthread_rwlock_t rwlock;  //读写锁

void *myread(void *arg)
{
while (1)
{
if(	pthread_rwlock_tryrdlock(&rwlock) != 0) //申请锁失败
{
printf("writer is working!\n");
printf("reader do othrer thing!\n");
continue;  //继续申请锁

}
else
{
printf("read:%d\n",buf);
pthread_rwlock_unlock(&rwlock); //释放锁
}
//	sleep(1);
}
}

void *mywrite(void *arg)
{
while(1)
{
if(pthread_rwlock_trywrlock(&rwlock) != 0)
{
printf("reader is working!\n");
printf("writer do other thing!\n");
continue;
}
else
{
buf++;
pthread_rwlock_unlock(&rwlock);
}

sleep(1);//写者隔1秒竞争一次锁资源
}
}

int main()
{
pthread_rwlock_init(&rwlock,NULL); //第二个参数是属性

pthread_t id1,id2;
pthread_create(&id1,NULL,myread,NULL);
pthread_create(&id2,NULL,mywrite,NULL);

pthread_join(id1,NULL);
pthread_join(id2,NULL);

pthread_rwlock_destroy(&rwlock);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 线程 读写锁