读写锁

(1) 读写锁是几把锁
  一把锁
  pthread_rwlock_t lock;

(2) 读写锁的类型
  读锁: 对内存做读操作
  写锁: 对内存做写操作

(3) 读写锁的特性:
  线程A加读锁成功, 又来了三个线程, 做读操作, 可以加锁成功
    读共享, 并行处理
  线程A加写锁成功, 又来了三个线程, 做读操作, 三个线程阻塞
    写读占, 串行处理
  线程A加读锁成功, 又来了B线程加写锁阻塞, 在B之后来了C线程加读锁阻塞
    读写不能同时进行
    写的优先级高

(4) 读写锁场景练习
线程A加写锁成功, 线程B请求读锁:
  线程B阻塞
线程A持有读锁, 线程B请求写锁:
  线程B阻塞
线程A拥有读锁, 线程B请求读锁
  线程B加锁成功
线程A持有读锁, 然后线程B请求写锁, 然后线程B请求读锁
  B阻塞, C阻塞 --> 写的优先级高
  A解锁, B线程加写锁成功, C继续阻塞
  B解锁, C加读锁成功
线程A持有写锁, 然后线程B请求读锁, 然后线程C请求写锁
  B, C阻塞
  A解锁, C加写锁, B阻塞
  C解锁, B加锁成功

(5) 读写锁使用场景
互斥锁--> 读写串行
读写锁--> 读: 并行; 写: 串行
程序中读操作大于写操作

(6) 主要处理函数
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); 初始化读写锁

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);销毁读写锁

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);加读锁
  阻塞: 之前对这把锁加的写锁的操作
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);尝试加读锁
  加锁成功: 0; 加锁失败: 错误号
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);加写锁
  阻塞: 上一次加写锁还没有解锁; 上一次加读锁没解锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);尝试加写锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);解锁

(7) 读写锁和互斥锁, 并不是任何时候都能阻塞线程

(8) 练习
3个线程不定时写同一全局资源, 5个线程不定时读同一全局资源

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>

int number = 0;

// 读写锁
pthread_rwlock_t lock;

void *write_func(void *arg) {
    while (1) {
        pthread_rwlock_wrlock(&lock);
        number++;
        printf("+++++write: %lu, %d\n", pthread_self(),  number);
        pthread_rwlock_unlock(&lock);
        sleep(1);
    }
    return NULL;
}

void *read_func(void *arg) {
    while (1) {
        pthread_rwlock_rdlock(&lock);
        printf("======read: %lu, %d\n", pthread_self(), number);
        pthread_rwlock_unlock(&lock);
        sleep(1);
    }
    return NULL;
}

int main() {
    int i;
    pthread_t p[8];

    // 初始化读写锁
    pthread_rwlock_init(&lock, NULL);

    // 3个写线程
    for (i = 0; i < 3; i++) {
        pthread_create(&p[i], NULL, write_func, NULL);
    }
    
    // 5个读线程
    for (i = 3; i < 8; i++) {
        pthread_create(&p[i], NULL, read_func, NULL);
    }

    // 回收子线程
    for (i = 0; i < 8; i++) {
        pthread_join(p[i], NULL);
    }

    for (i = 0; i < 8; i++) {
        pthread_rwlock_destroy(&lock);
    }

    return 0;
}
posted @ 2019-04-19 21:38  张飘扬  阅读(1491)  评论(0编辑  收藏  举报