线程同步 读写锁

发布时间 2023-08-30 14:08:32作者: LiviaYu

读写锁

一把锁,并不是读锁和写锁
称之为读写锁,因为他既可以锁定读操作,也可以锁定写操作

pthread_rwlock_t rwlock;

锁中记录了

  • 锁的状态 打开关闭
  • 锁定的操作 锁读 锁写
  • 哪个线程持有钥匙

使用方式和互斥锁相同:

  1. 找共享资源
  2. 确定临界区
  3. 临界区加锁,解锁

特点

  1. 读锁锁定了临界区,线程对临界区的访问是并行的,读锁共享
  2. 写锁锁定了临界区,线程对临界区的访问是串行的,写锁独占
  3. 多个请求读写锁,写锁优先

读操作多时,可以选用读写锁,效率较高

函数

初始化和析构

#include<pthread_h>
pthread_rwlock_t rwlock;
//初始化读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
     const pthread_rwlockattr_t *restrict attr);
//释放资源
pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

rwlock 读写锁的地址,传出参数

读锁

//加读锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

调用这个函数,如果读写锁是打开的,那么加锁成功;如果读写锁已经锁定了读操作,调用这个函数依然可以加锁成功,因为读锁是共享的;
如果读写锁已经锁定了写操作,调用这个函数的线程会被阻塞

// 这个函数可以有效的避免死锁
// 如果加读锁失败, 不会阻塞当前线程, 直接返回错误号
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

写锁

// 在程序中对读写锁加写锁, 锁定的是写操作
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

如果读写锁是没上锁的,那么加锁成功。如果读写锁已经锁定,那么阻塞操作

同样有try加锁的命令

// 这个函数可以有效的避免死锁
// 如果加写锁失败, 不会阻塞当前线程, 直接返回错误号
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

解锁

//读写锁都可以解锁
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock);

读写锁使用

写一个程序,有5个线程对全局变量进行读操作,3个线程进行写操作

#include <pthread.h>
#include <iostream>
#include <bits/stdc++.h>
#include <unistd.h>
#define MAX 50
// 全局变量
int number;

pthread_rwlock_t rwlock1;

using namespace std;

void *read_num(void *arg)
{
    for (int i = 0; i < MAX; i++)
    {
        pthread_rwlock_rdlock(&rwlock1);
        cout << "thread read,id= " << pthread_self() << " number= " << number << endl;
        pthread_rwlock_unlock(&rwlock1);
        usleep(rand() % 5);
    }
    return NULL;
}
void *write_num(void *arg)
{
    for (int i = 0; i < MAX; i++)
    {
        pthread_rwlock_wrlock(&rwlock1);
        int cur=number;
        cur++;
        number=cur;
        cout << "thread write,id= " << pthread_self() << " number= " << number << endl;
        pthread_rwlock_unlock(&rwlock1);
    };
    return NULL;
}

int main()
{
    pthread_t p1[5], p2[3];
    // 初始化锁
    pthread_rwlock_init(&rwlock1, NULL);

    // 5个读线程,3个写线程
    for (int i = 0; i < 5; i++)
    {
        pthread_create(&p1[i], NULL, read_num, NULL);
    }
    for (int i = 0; i < 3; i++)
    {
        pthread_create(&p1[i], NULL, write_num, NULL);
    }

    // 阻塞后资源回收
    for (int i = 0; i < 5; i++)
    {
        pthread_join(p1[i], NULL);
    }
    for (int i = 0; i < 3; i++)
    {
        pthread_join(p2[i], NULL);
    }
    // 释放锁
    pthread_rwlock_destroy(&rwlock1);
    return 0;
}

实现结果