读写锁

 

 1、概述

  读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态,要么是不加锁状态,而且一次只有一个线程对其加锁。读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可用同时占有读模式的读写锁。读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的,当它以写模式锁住时,它是以独占模式锁住的。

2、读写锁API

  读写锁的数据类型为pthread_rwlock_t。如果这个类型的某个变量是静态分配的,那么可通过给它赋常值PTHREAD_RWLOCK_INITIALIZER来初始化它。

获取和释放读写锁:
int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr); //获取一个读出锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr); //获取一个写入锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwptr); //释放一个写入锁或者读出锁
都返回:成功时为0,出错时为正的Exxx值
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwptr);
都返回:成功时为0,出错时为正的Exxx值

读写锁属性:
int pthread_rwlock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr)
int pthread_rwlock_destroy(pthread_rwlock_t *rwptr);
都返回:成功时为0,出错时为正的Exxx值

int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
都返回:成功时为0,出错时为正的Exxx值

int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *valptr);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int valptr);
都返回:成功时为0,出错时为正的Exxx值

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h> #define MAXDATA 1024
#define MAXREDER 100
#define MAXWRITER 100
struct
{
pthread_rwlock_t rwlock;
char datas[MAXDATA];
} shared = {
PTHREAD_RWLOCK_INITIALIZER
}; void *reader(void *arg);
void *writer(void *arg); int main(int argc,char *argv[])
{
int i,readercount,writercount;
pthread_t tid_reader[MAXREDER],tid_writer[MAXWRITER];
if(argc != )
{
printf("usage : <reader_writer> #<readercount> #<writercount>\n");
exit();
}
readercount = atoi(argv[]);
writercount = atoi(argv[]);
pthread_setconcurrency(readercount+writercount);
for(i=;i<writercount;++i)
pthread_create(&tid_writer[i],NULL,writer,NULL);
sleep();
for(i=;i<readercount;++i)
pthread_create(&tid_reader[i],NULL,reader,NULL);
for(i=;i<writercount;++i)
pthread_join(tid_writer[i],NULL);
for(i=;i<readercount;++i)
pthread_join(tid_reader[i],NULL);
exit();
}
void *reader(void *arg)
{
pthread_rwlock_rdlock(&shared.rwlock);
printf("Reader begins read message.\n");
sleep();
printf("Read message is: %s\n",shared.datas);
pthread_rwlock_unlock(&shared.rwlock);
return NULL;
} void *writer(void *arg)
{
char datas[MAXDATA];
pthread_rwlock_wrlock(&shared.rwlock);
printf("Writers begings write message.\n");
printf("Enter the write message: \n");
gets(datas);
strcat(shared.datas,datas);
pthread_rwlock_unlock(&shared.rwlock);
return NULL;
}

打印输出

[root@localhost pthread_rwlock]# ./run
Writers begings write message.
Enter the write message:
sdfs
Reader begins read message.
Reader begins read message.
Reader begins read message.
Reader begins read message.
Reader begins read message.
Read message is: sdfs
Read message is: sdfs
Read message is: sdfs
Read message is: sdfs
Read message is: sdfs
[root@localhost pthread_rwlock]#

我在read中加入sleep,看家其他read线程也进入了,表明一次只有一个线程可以占有写模式的读写锁,但是多个线程可用同时占有读模式的读写锁。

另外请关注pthread_setconcurrency();

最近在code review一些人的代码的时候,发现了一个问题,就是很少人关注pthread_setconcurrency()函数,其实这个函数在pthread中是一个很重要的函数。在linux下,如果你忽略了这个函数的使用,那么能够并发的线程数目由实现者来控制,对于系统调度的效率而言往往不是什么好的事情,因为默认的设置往往不是最佳的。
     更为糟糕的是,如果在某些系统中,如果你不调用pthread_setconcurrency()函数,那么系统中的运行的线程仅仅是第一个被创建的线程,其他线程根本不会被运行。比如在solaris 2。6中就有这些情况。为了在unix或者是linux系统上使移植更加的容易,请不要忘记在适当的地方调用次函数,清晰的告诉系统我们使用的线程个数。虽然在某些系统上,这个调用是徒劳的,但是它的使用增强的移植性!

pthread_rwlock的更多相关文章

  1. pthread_rwlock pthread读写锁

    原文: http://www.cnblogs.com/diegodu/p/3890450.html 使用读写锁 配置读写锁的属性之后,即可初始化读写锁.以下函数用于初始化或销毁读写锁.锁定或解除锁定读 ...

  2. linux线程同步(3)-读写锁

    一.概述                                                    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...

  3. Linux同步机制(一) - 线程锁

    1 互斥锁 在线程实际运行过程中,我们经常需要多个线程保持同步. 这时可以用互斥锁来完成任务.互斥锁的使用过程中,主要有 pthread_mutex_init pthread_mutex_destor ...

  4. Innodb 锁系列1 同步机制

    同步机制 Innodb实现了不依赖于平台的mutex,rwlock. 1. 全局变量 对于mutex, rwlock,都有一个全局链表. 1. mutex全局链表:mutex_list 2. rwlo ...

  5. Mudo C++网络库第四章学习笔记

    C++多线程系统编程精要 学习多线程编程面临的最大思维方式的转变有两点: 当前线程可能被切换出去, 或者说被抢占(preempt)了; 多线程程序中事件的发生顺序不再有全局统一的先后关系; 当线程被切 ...

  6. iOS 线程安全

    线程安全: 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.就好比几个人在同一时修改同一个表格,造成数据的错乱. 解决多线程安全问题的方法 方法一:互斥锁(同步锁) @synchroni ...

  7. linux读写锁

    一.概述                                                    读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...

  8. iOS 中的各种锁

    在日常开发过程中,为了提升程序运行效率,以及用户体验,我们经常使用多线程.在使用多线程的过程中,难免会遇到资源竞争问题.我们采用锁的机制来确保线程安全. 线程安全 当一个线程访问数据的时候,其他的线程 ...

  9. Linux/UNIX线程(2)

    线程(2) 线程同步 当多个控制线程共享同样内存时,须要确保每一个线程看到一致的数据视图.假设每一个线程使用的变量都是其它线程不会读取或改动的,那么就不在一致性问题. 当两个或多个线程试图在同一时间改 ...

随机推荐

  1. Ajax实现异步操作实例_针对XML格式的请求数据

    js分类中有一节[原生js异步请求,XML解析]主要说明了js前台是如何处理XML格式请求和如何接受由服务器返回的XML数据的解析,今天我将用一个实例来说明具体要如何操作. 前台的参数类型也是XML使 ...

  2. PowerDesigner打开设计文件后提示failed to read the fileXXX的解决办法

    擦,一身盗汗.一向的设计信息都在设计图里!竟然坏了,坏了!!!!! 惊.怒.悲 固然可以经由过程数据库当前状况反向工程.然则那么注解.我写的提示这些器材都邑消散. 比来的备份是10天前,恢复也会有必然 ...

  3. Django1.8教程——从零开始搭建一个完整django博客(三)

    这一节主要介绍对数据库的访问操作:通过管理器(manage),对对象进行检索.修改.删除等操作,详细介绍了如何针对不同的模型自定义管理器. 查询和管理工作 现在,我们已经有了一个功能完善的Django ...

  4. grootJs 属性过滤器

    index10.html <html><head> <title>属性过滤器</title> <script src="jquery-1 ...

  5. 自己写了个H5版本的俄罗斯方块

    在实习公司做完项目后,实在无聊.就用H5写了几个游戏出来玩一下.从简单的做起,就搞了个经典的俄罗斯方块游戏. 先上效果: 上面的数字是得分,游戏没有考虑兼容性,只在chrome上测试过,不过大部分现代 ...

  6. C# 6.0部分新特性

    Struct的默认构造函数和属性赋值 我看C# 6 introduce 提到这个功能.但vs2015搭载的NET4.6貌似还不支持这个.所以也不好判断. 属性赋值 /// <summary> ...

  7. OC基础--description方法

    PS:经过之类重写description方法后,个人感觉有点像C#中的ToString();方法 一.description方法的作用:(输出所有的OC对象都用%@) 1.默认情况下(不重写descr ...

  8. C基础--C语言的数组

    数组的定义: 一.正确写法: 1.int ages[5]--定义了一个5个长度的int类型的数组 2.int ages[]={1,2,3,4,5};--定义了一个5个长度的int类型的数组,并且初始化 ...

  9. LINQ构建交叉表

    最近碰到客户的一个需求.使用交叉表来显示客户数据.也就是以同时以行头和列头交叉形式显示数据内容.同时要求即使有些列没有数据,也需要显示该列内容,并设置默认值. 说明: “交叉表”对象是一个网格,用来根 ...

  10. 小菜鸟学 MQ(一)

    第一步: 从http://activemq.apache.org/ 下载相关文件. apache-activemq-5.8.0-bin.zip 解压到指定目录下. 第二步: cmd 下切换到   mq ...