pthread 读写锁 (Read Write Lock, rwlock) 把对共享资源的访问者分为读者和写者,读者仅仅对共享资源进行读访问,写者仅仅对共享资源进行写操作。

如果使用互斥量 mutex,读者和写者都必须独占 mutex 以独占共享资源,在读写锁机制下,同一时刻允许有多个读者读访问共享资源,仅仅有写者才须要独占资源。相比互斥量,读写锁因为允许多个读者同一时候访问共享资源,进一步提高了多线程的并发度。

API

相关数据结构:

  • pthread_rwlock_t : 读写锁的数据结构;
  • pthread_rwlockattr_t : 读写锁属性的数据结构。

init and destroy

函数原型:

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

作用:初始化/销毁一个读写锁。

rdlock/tryrdlock/timedrdlock

函数原型:

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);

作用:

  • rdlock 申请读锁 rwlock ,若申请失败则阻塞当前线程;
  • tryrdlock 如果申请失败会立即返回,而不会阻塞线程;
  • timedrdlock 申请读锁 rwlock,如果申请失败,会阻塞线程直到某一时刻,该时刻由 abs_timeout 指定。

wrlock/trywrlock/timedwrlock

函数原型:

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);

作用:与 rdlock 类似。

unlock

函数原型:

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

作用:释放 rwlock .

Example

参考 APUE 一书的例子。

在本节中,通过读写锁机制实现以下场景:存在一个任务队列,需要由多线程并发完成队列中的任务,但是任务的分配由主线程完成,主线程把该任务所属的线程 ID j_id 放在任务的数据结构中,只有该 j_id 线程才能操作这一任务。

通过读写锁机制实现上述任务队列 queue 的并发控制:允许多个线程读取队列,但只允许单个线程修改队列。

代码实现:

#include <stdlib.h>
#include <pthread.h>
struct job
{
struct job *j_next;
struct job *j_prev;
pthread_t j_id; /* tells which thread handles this job */
/* ... more stuff here ... */
};
struct queue
{
struct job *q_head;
struct job *q_tail;
pthread_rwlock_t q_lock;
}; /*
* Initialize a queue.
*/
int queue_init(struct queue *qp)
{
int err; qp->q_head = NULL;
qp->q_tail = NULL;
err = pthread_rwlock_init(&qp->q_lock, NULL);
if (err != 0)
return (err);
/* ... continue initialization ... */
return (0);
} /*
* Insert a job at the head of the queue.
*/
void job_insert(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = qp->q_head;
jp->j_prev = NULL;
if (qp->q_head != NULL)
qp->q_head->j_prev = jp;
else
qp->q_tail = jp; /* list was empty */
qp->q_head = jp;
pthread_rwlock_unlock(&qp->q_lock);
} /*
* Append a job on the tail of the queue.
*/
void job_append(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
jp->j_next = NULL;
jp->j_prev = qp->q_tail;
if (qp->q_tail != NULL)
qp->q_tail->j_next = jp;
else
qp->q_head = jp; /* list was empty */
qp->q_tail = jp;
pthread_rwlock_unlock(&qp->q_lock);
} /*
* Remove the given job from a queue.
*/
void job_remove(struct queue *qp, struct job *jp)
{
pthread_rwlock_wrlock(&qp->q_lock);
if (jp == qp->q_head)
{
qp->q_head = jp->j_next;
if (qp->q_tail == jp)
qp->q_tail = NULL;
else
jp->j_next->j_prev = jp->j_prev;
}
else if (jp == qp->q_tail)
{
qp->q_tail = jp->j_prev;
jp->j_prev->j_next = jp->j_next;
}
else
{
jp->j_prev->j_next = jp->j_next;
jp->j_next->j_prev = jp->j_prev;
}
pthread_rwlock_unlock(&qp->q_lock);
} /*
* Find a job for the given thread ID.
*/
struct job *job_find(struct queue *qp, pthread_t id)
{
struct job *jp; if (pthread_rwlock_rdlock(&qp->q_lock) != 0)
return (NULL); for (jp = qp->q_head; jp != NULL; jp = jp->j_next)
if (pthread_equal(jp->j_id, id))
break; pthread_rwlock_unlock(&qp->q_lock);
return (jp);
}

pthread 读写锁的更多相关文章

  1. 【C/C++多线程编程之九】pthread读写锁

    多线程编程之读写锁      Pthread是 POSIX threads 的简称,是POSIX的线程标准.         pthread读写锁把对共享资源的訪问者分为读者和写者,读者仅仅对共享资源 ...

  2. pthread_rwlock pthread读写锁

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

  3. c++ 读写锁

    #ifndef THREAD_UTIL_H #define THREAD_UTIL_H #include <pthread.h> namespace spider { class Auto ...

  4. pthread中读写锁

    读写锁很像一个互斥量,他阻止多个线程同时修改共享数据的另一种方法,区分不同互斥量的是他是分读数据和写数据,一个读写锁允许同时多个线程读数据,只要他们不修改数据. 只要没有写模式下的加锁,任意线程都可以 ...

  5. 基于pthread实现读写锁

    读写锁可用于在多线程访问map等数据结构时使用 #include <pthread.h> class ReadWriteLock { public: ReadWriteLock() { p ...

  6. 读写锁(pthread)

    读写锁: 用于对于某个给定资源的共享访问,而不是像互斥锁那样,将所有试图进入临界区的线程都阻塞住 相关内容: 线程互斥锁 分配规则:(写独占,读共享) 1.只要没有线程持有某个给定的读写锁用于写,那么 ...

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

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

  8. linux 读写锁应用实例

    转自:http://blog.csdn.net/dsg333/article/details/22113489 /*使用读写锁实现四个线程读写一段程序的实例,共创建了四个新的线程,其中两个线程用来读取 ...

  9. linux使用读写锁pthread_rwlock_t

    转自:http://blog.csdn.net/onlyou930/article/details/6755593 使用读写锁 配置读写锁的属性之后,即可初始化读写锁.以下函数用于初始化或销毁读写锁. ...

随机推荐

  1. LeetCode初级算法之字符串:7 整数反转

    整数反转 题目地址:https://leetcode-cn.com/problems/reverse-integer/ 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 ...

  2. 理解js浅拷贝和深拷贝

    理解深拷贝和浅拷贝之前先了解下js中的基本类型和引用类型 1.基本类型: 在js中,数据的基本类型undefined,null,string,number,boolean,在变量中赋的实际值,基本类型 ...

  3. Panda 交易所快报 央行数字货币测试进入C端流量入口

    近年来,央行数字货币的研发进展备受市场关注.近期,Panda 交易所注意,央行数字货币研究所与滴滴出行已达成战略合作协议,共同研究探索数字人民币在智慧出行领域的场景创新和应用.此外,Panda 交易所 ...

  4. B树——插入和删除

    B树--插入和删除 B树的插入 5阶B数--结点关键字个数向上取整m/2-1≤n≤m-1 即2≤n≤4 连续插入5个元素后,超出来了. 在插入key后,若导致原结点关键字数超过上限,则从中间位置(m/ ...

  5. Python 学习笔记 之 随着学习不断更新的Python特性搜集

    大小写敏感 缩进敏感--tab和空格不要混用,最好使用4个空格进行缩进.可使用vim配置缩进字符为4个空格 编写py文件时注意文件的编码,UTF-8 without BOM, 并且记得声明coding

  6. springmvc中使用文件上传功能

    项目代码:https://github.com/PeiranZhang/springmvc-fileupload Servlet3.0之前使用文件上传功能 Servlet3.0之前需要使用common ...

  7. css进阶 06-CSS开发积累

    06-CSS开发积累 #让flex盒子中的子元素们,居中 flex布局常用的三行代码: display: flex; justify-content: center; // 子元素在横轴的对齐方式 ( ...

  8. Java 方法内联

    什么是Java 方法内联? 我们先来看看普遍的内联函数含义.在维基百科中解释为: 内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函 ...

  9. 超简单的 Docker部署 SpringBoot项目 步骤

    很久之前就用过,一直没有好好写篇博客,今天就总结一下 创建一个 SpringBoot项目 创建一个SpringBoot项目并打成jar包,结构如图 编写 Dockerfile文件 FROM java: ...

  10. (九)rmdir和rm -r删除目录命令

    一.命令描述与格式 rmdir用于删除空目录 命令格式 :rmdir   [选项]   目录名 选项: --ignore-fail-on-non-empty   :忽略任何因目录仍有数据而造成的错误 ...