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. CF1406E 【Deleting Numbers】

    蒟蒻语 蒟蒻这次 \(CF\) 又双叒叕掉分了,\(C\) 都没有调出来. 还好再最后 \(10\) 秒钟调了下 \(E\) 块长 (块长 \(100\) => \(98\)),才没有掉得那么惨 ...

  2. 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)

    Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...

  3. 2020中国.NET开发者峰会近50场热点技术专题揭秘

    简介 / Summary 2014年微软组织并成立.NET基金会,微软在成为主要的开源参与者的道路上又前进了一步.2014年以来已经有众多知名公司加入.NET基金会,微软,Google,AWS三大云厂 ...

  4. Vue组件化开发(原有项目的改造)

    将组件定义成一个js和css,然后供其他页面进行调用 demo.html <!DOCTYPE html> <html> <head> <meta charse ...

  5. 博流BL602&BL604开发板介绍

    在2020松山湖论坛上,博流智能科技(南京)有限公司销售副总裁刘占领介绍了基于RISC-V核的低功耗.高可靠Wi-Fi+BLE二合一SoC芯片BL602.主要应用领域包括人工智能与工业互联网,特别是电 ...

  6. 学习笔记: mysql增删改查基础语句

    mysql基础入门语句 增: INSERT INTO 表名(字段1, 2, 3) VALUES('值1', '2', '3') 删: DELETE FROM 表明 WHERE 删除条件 不提供更新条件 ...

  7. Echarts入门教程精简实用系列

    引语:echarts.js是百度团队推出的一款用于图表可视化的插件,用于以图表的形式展现数据,功能强大,上手简单 1.从官方网站中下载所需的echarts.js文件,该文件因功能广泛,包体较大,可自行 ...

  8. C++异常之七 标准库里的异常类

    标准库里的异常类 C++标准提供了一组标准异常类,这些类以基类 Exception 开始,标准程序库抛出的所有异常,都派生于该基类,这些类构成如图所示的异常类的派生继承关系,该基类提供一个成员函数 w ...

  9. 精尽Spring MVC源码分析 - HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  10. js下 Day17、综合案例

    一.面向对象轮播 效果图: