Linux线程浅析[线程的同步和互斥之线程读写锁]
2017-03-31 22:27
267 查看
Linux线程浅析[线程的同步和互斥之线程读写锁]
读写锁的出现是为了解决互斥锁的弊端使用上述Linux线程浅析[线程的同步和互斥之线程互斥锁]的案例来进行解释吧,即针对上述案例中的银行存取款的互斥锁,当一个账户去访问的时候,另外一个账户其实就需要被阻塞,但是现实中往往会有这样一种情况,一个人去存,但是其余的人是去查询,如果存的人获取了锁,那么查询的人就需要被阻塞,这就导致了查询效率极低的这样的一种情况
什么是读写锁:
概念:读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
读写锁的使用场景:
线程互斥——读写锁
线程使用互斥锁缺乏读并发性
当读操作较多时,写操作较少时,可以使用读写锁来提高线程读并发性
读写锁: pthread_rwlock_t
读写锁的相关函数:
#include<pthread.h> int pthread_wrlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr); int ptrhead_wrlock_destory(pthread_rwlock_t *rwlock) 成功:返回0,出错返回错误编码 参数: rwlock:读写锁 attr:读写锁属性
读写锁加锁和加写锁
#include<pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) 功能:加读锁 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) 功能:加写锁 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) 功能:释放锁 返回:成功返回0,失败返回错误编码 参数:rwlock:读写锁
如下表格所示:
类型 | readlock | writelock |
---|---|---|
readlock | 读锁和读锁不排斥 | 先写锁成功,读锁失败 |
writelock | 先读锁成功,写锁阻塞 | 先写成功,后写失败 |
1:如果一个函数上了读锁,两个线程一起调用的时候是不会发生排斥现象的(不排斥)
2:如果一个函数上了读锁,另一个函数上了写锁,那么线程一先调用读锁函数,线程二再调用写锁函数的时候,这个时候线程二是会阻塞住的(排斥)
3:如果一个函数上了读锁,另外一个函数上了写锁,当线程一先调用写锁函数,线程二再调用读锁函数的时候,这个时候线程二是会加锁失败(排斥)
4:一个函数上了写锁,两个线程同时调用写锁函数.第一个调用成功,第二个会失败(排斥)
那么通过读写锁的形式对原来互斥锁的银行案例进行修改:
/* * =========================================================================== * * Filename: account.h * Description: * Version: 1.0 * Created: 2017年03月28日 22时04分18秒 * Revision: none * Compiler: gcc * Author: (), * Company: * * =========================================================================== */ #ifndef __ACCOUNT_H_ #define __ACCOUNT_H_ //声明银行账户的结构体 //引用pthread头文件.方便后面加锁 #include<pthread.h> typedef struct{ int code; double balance; //将锁声明在结构体中,有助于每一个这样的结构体都有一把锁,那么在操作的时候,有利于优化并发效果 //pthread_mutex_t pthreadmutex; pthread_rwlock_t pthreadrwlock; }Account; //创建银行账户 extern Account* create_account(int code,double balance); //销毁一个账户 extern void destory_account(Account* account); //存款 extern double withdraw(Account* account,double amt); //取款 extern double deposit(Account* a,double amt); //查看账户余额 extern double get_balance(Account* account); #endif
/* * =========================================================================== * * Filename: account.c * Description: * Version: 1.0 * Created: 2017年03月30日 21时16分28秒 * Revision: none * Compiler: gcc * Author: (), * Company: * * =========================================================================== */ #include"account.h" #include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h> #include<assert.h> #include<pthread.h> //static pthread_mutexattr_t attr; /* *创建一个账户 *返回这个账户的指针 * * */ extern Account* create_account(int code,double balance){ Account* account = (Account*)malloc(sizeof(Account)); assert(account !=NULL); account->code = code; account->balance = balance; //初始化锁的过程 //pthread_mutexattr_init(&attr); //pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_NORMAL); //pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); //pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK); //pthread_mutex_init(&account->pthreadmutex,NULL); //pthread_mutex_init(&account->pthreadmutex,&attr); //初始化读写锁 pthread_rwlock_init(&account->pthreadrwlock,NULL); return account; } /* * *销毁一个账户 * */ extern void destory_account(Account* account){ assert(account!=NULL); free(account); //销毁锁的过程 //pthread_mutexattr_destroy(&attr); //pthread_mutex_destroy(&account->pthreadmutex); // //销毁读写锁 pthread_rwlock_destroy(&account->pthreadrwlock); } /* * *取款,返回的是账户的余额 * * */ extern double withdraw(Account * account,double amt){ assert(account != NULL); //上锁的过程 //pthread_mutex_lock(&account->pthreadmutex); //上读写锁(读锁) pthread_rwlock_wrlock(&account->pthreadrwlock); if(amt < 0 || amt > account->balance){ //解锁的过程 //pthread_mutex_unlock(&account->pthreadmutex); // //解读写锁 pthread_rwlock_unlock(&account->pthreadrwlock); return 0.0; } int balance = account -> balance; sleep(1); int result = balance - amt; account ->balance = result; //解锁的过程 //pthread_mutex_unlock(&account->pthreadmutex); // //解读写锁 pthread_rwlock_unlock(&account->pthreadrwlock); return amt; } /* * *存款,返回的也是账户的余额 * * */ extern double deposit(Account* account,double amt){ assert(account != NULL); //上锁的过程 //pthread_mutex_lock(&account->pthreadmutex); //上读写锁(读锁) pthread_rwlock_wrlock(&account->pthreadrwlock); if(amt < 0){ //解锁的过程 //pthread_mutex_unlock(&account->pthreadmutex); //解读写锁 pthread_rwlock_unlock(&account->pthreadrwlock); return 0.0; } int balance = account ->balance; sleep(2); int result = balance + amt; account->balance = result; //解锁的过程 //pthread_mutex_unlock(&account->pthreadmutex); //解读写锁 pthread_rwlock_unlock(&account->pthreadrwlock); return result; } /* * *获取的就是这个账户的余额 * * */ extern double get_balance(Account* account){ assert(account !=NULL); //上读写锁(读锁) pthread_rwlock_rdlock(&account->pthreadrwlock); int result = account->balance; //解决读写锁 pthread_rwlock_unlock(&account->pthreadrwlock); return result; }
其他部分的执行代码在互斥锁中有,所以在这里就不去赘述了.
欢迎持续访问博客
相关文章推荐
- Linux线程浅析[线程的同步和互斥之线程互斥锁]
- Linux — 浅析线程以及多线程的同步与互斥
- Linux线程浅析[线程的同步和互斥之线程死锁,线程与信号的关系]
- linux操作系统编程——共享内存的读写(采用信号机制进行同步互斥)
- Linux多线程编程(不限Linux)——本文一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- Linux多线程编程(二)---线程之间的同步与互斥
- linux信号量实现线程读写同步
- Linux下线程的同步与互斥
- linux操作系统编程——共享内存读写(采用信号量进行同步互斥)
- 一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- linux下线程的同步和互斥
- linux 系统编程-学习笔记9--线程的同步互斥锁、读写锁/select/poll
- Linux环境下线程的同步与互斥以及死锁问题
- 讲Linux下面线程的操作、多线程的同步和互斥相关函数及操作的文章链接
- linux 线程创建 同步与互斥
- 讲Linux下面线程的操作、多线程的同步和互斥相关函数及操作的文章链接
- 介绍Linux下面线程的操作、多线程的同步和互斥
- <转>linux操作系统编程——共享内存读写(采用信号量进行同步互斥)
- 关于linux中多进程(线程)同步和互斥
- Linux之线程:同步与互斥