【线程同步】读写锁

2024-08-08 17:19:32 浏览数 (3)

1. 什么是读写锁

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

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

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

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

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

2. 读写锁相关API

2.1 读写锁的初始化与释放

  • 头文件及函数原型
代码语言:javascript复制
#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 加读锁

  • 头文件及函数原型
代码语言:javascript复制
#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 加写锁

  • 头文件及函数原型
代码语言:javascript复制
#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 释放锁

  • 头文件及函数原型
代码语言:javascript复制
#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. 案例分析

代码语言:javascript复制
#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: %dn", __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: %dn", __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;
}

0 人点赞