【Linux线程同步专题】二、读写锁

简介: 【Linux线程同步专题】二、读写锁

1. 什么是读写锁

读写锁是一种与互斥量类似的锁,它允许更高的并行性,具有写独占,读共享的特点。读写锁总共有三种状态:

  • 读模式下加锁状态(读锁)
  • 写模式下加锁状态(写锁)
  • 不加锁状态

读写锁,所谓读共享写独占是指,加读锁的时候,可以多线程一块读,但是不能写;加写锁的时候,不能读,只有当前线程可以写。并且写优先级高于读。读写锁是一把锁,有上面三种状态。

  • 读写锁是写模式加锁的时候,解锁前,所有对该锁加锁的线程都会被阻塞;
  • 读写锁是读模式加锁的时候,如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞;
  • 读写锁是读模式加锁时,既有试图以写模式加锁的线程,又有以读模式加锁的线程,那么读写锁会阻塞随后的读模式加锁请求,优先满足写模式加锁。读锁写锁并行阻塞,写锁优先级高,也就是说线程1持有写锁,线程2请求写锁的同时线程3请求读锁(如果没有写锁申请,那么读锁加锁成功),这时候线程2和3都阻塞,线程1释放锁后,优先满足线程2写锁。

读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的,也就是所谓的写独占,读共享。读写锁适用于对数据结构读的次数远大于写的情况,因为多线程加读锁的时候可以同时读,效率更高。

2. 读写锁相关API

2.1 读写锁的初始化与释放

  • 头文件及函数原型
#include <pthread.h>
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
  • 函数描述
  • The pthread_rwlock_destroy() function shall destroy the read-write lock object referenced by rwlock and release any resources used by the lock.
  • The pthread_rwlock_init() function shall allocate any resources required to use the read-write lock referenced by rwlock and initializes the lock to an unlocked state with attributes referenced by attr.
  • 函数参数
  • 函数返回值
    If successful, the pthread_rwlock_destroy() and pthread_rwlock_init() functions shall return zero; otherwise, an error number shall be returned to indicate the error.

2.2 加读锁

  • 头文件及函数原型
#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  • 函数描述
  • The pthread_rwlock_rdlock() function shall apply a read lock to the read-write lock referenced by rwlock.
  • The pthread_rwlock_tryrdlock() function shall apply a read lock as in the pthread_rwlock_rdlock() function, with the exception that the function shall fail if the equivalent pthread_rwlock_rdlock() call would have blocked the calling thread.
  • 函数参数
  • 函数返回值
  • If successful, the pthread_rwlock_rdlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.
  • The pthread_rwlock_tryrdlock() function shall return zero if the lock for reading on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.

2.3 加写锁

  • 头文件及函数原型
#include <pthread.h>
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  • 函数描述
    The pthread_rwlock_trywrlock() function shall apply a write lock like the pthread_rwlock_wrlock() function, with the exception that the function shall fail if any thread currently holds rwlock (for reading or writing).
  • 函数参数
  • 函数返回值
  • The pthread_rwlock_trywrlock() function shall return zero if the lock for writing on the read-write lock object referenced by rwlock is acquired. Otherwise, an error number shall be returned to indicate the error.
  • If successful, the pthread_rwlock_wrlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.

2.4 释放锁

  • 头文件及函数原型
#include <pthread.h>
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  • 函数描述
    The pthread_rwlock_unlock() function shall release a lock held on the read-write lock object referenced by rwlock.
  • 函数参数
  • 函数返回值
    If successful, the pthread_rwlock_unlock() function shall return zero; otherwise, an error number shall be returned to indicate the error.

3. 案例分析

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
int gdata = 100;
void* read_th(void* arg)
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("read thread: %s, tid: %d, gdata: %d\n", __FUNCTION__, pthread_self(), gdata);
        usleep(8000);
        pthread_rwlock_unlock(&rwlock);
        usleep(6000);
    }
}
void* write_th(void* arg)
{
    while(1)
    {
        pthread_rwlock_wrlock(&rwlock);
        printf("write thread: %s, tid: %d, gdata: %d\n", __FUNCTION__, pthread_self(), ++gdata);
        usleep(8000);
        pthread_rwlock_unlock(&rwlock);
        usleep(9000);
    }
}
int main(int argc, char* argv[])
{
    pthread_t tid[6];
    for(i = 0; i < 4; i++)
    {
        pthread_create(&tid[i], NULL, read_th, NULL);
    }
    for(; i< 6; i++)
    {
        pthread_join(&tid[i], NULL, write_th, NULL);
    }
    for(i = 0; i < 6; i++)
    {
        pthread_join(tid[i], NULL);
    }
    return 0;
}


相关文章
|
16天前
|
Linux C++
LInux下Posix的传统线程示例
LInux下Posix的传统线程示例
15 1
|
22天前
|
算法 Unix Linux
Linux与Qt线程优先级的对应关系:一次全面解析
Linux与Qt线程优先级的对应关系:一次全面解析
21 0
|
24天前
|
消息中间件 Linux 调度
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
63 0
|
29天前
|
资源调度 算法 Linux
Linux进程/线程的调度机制介绍:详细解析Linux系统中进程/线程的调度优先级规则
Linux进程/线程的调度机制介绍:详细解析Linux系统中进程/线程的调度优先级规则
48 0
|
4天前
|
Java 程序员 编译器
Java中的线程同步与锁优化策略
【4月更文挑战第14天】在多线程编程中,线程同步是确保数据一致性和程序正确性的关键。Java提供了多种机制来实现线程同步,其中最常用的是synchronized关键字和Lock接口。本文将深入探讨Java中的线程同步问题,并分析如何通过锁优化策略提高程序性能。我们将首先介绍线程同步的基本概念,然后详细讨论synchronized和Lock的使用及优缺点,最后探讨一些锁优化技巧,如锁粗化、锁消除和读写锁等。
|
12天前
|
安全 Java 调度
深入理解Java中的线程安全与锁机制
【4月更文挑战第6天】 在并发编程领域,Java语言提供了强大的线程支持和同步机制来确保多线程环境下的数据一致性和线程安全性。本文将深入探讨Java中线程安全的概念、常见的线程安全问题以及如何使用不同的锁机制来解决这些问题。我们将从基本的synchronized关键字开始,到显式锁(如ReentrantLock),再到读写锁(ReadWriteLock)的讨论,并结合实例代码来展示它们在实际开发中的应用。通过本文,读者不仅能够理解线程安全的重要性,还能掌握如何有效地在Java中应用各种锁机制以保障程序的稳定运行。
|
22天前
|
存储 算法 Linux
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
24 0
|
29天前
|
消息中间件 并行计算 网络协议
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
33 0
|
Linux
linux下使用读写锁
    在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。     处理读写着问题的两种常见策略是:强读者同步和强写者同步。
745 0
|
9天前
|
Web App开发 Linux 网络安全
工作中常用到的Linux命令
工作中常用到的Linux命令