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

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起探讨和分享Linux C/C++/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。



专栏传送门 :《Linux从小白到大神》 | 系统学习Linux开发、VIM/GCC/GDB/Make工具、Linux文件IO、进程管理、进程通信、多线程等,请关注专栏免费学习。


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;
}

在这里插入图片描述
在这里插入图片描述


posted @ 2022-10-04 21:22  Mindtechnist  阅读(94)  评论(0编辑  收藏  举报  来源