Linux线程浅析[线程的同步和互斥之线程读写锁]

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:读写锁

 如下表格所示:

类型readlockwritelock
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;
}

其他部分的执行代码在互斥锁中有,所以在这里就不去赘述了.

欢迎持续访问博客

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值