zoukankan      html  css  js  c++  java
  • 读写锁

    (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
    ", 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
    ", 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;
    }
    
  • 相关阅读:
    VB Treeview控件 介绍与使用
    基于V4L2的视频驱动开发
    Jlinkv8 灯不亮重新烧写固件的办法
    使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法
    linux 开机自动执行脚本或者一些指定的程序
    FrameBuffer编程二(简单程序下)
    c语言内存分配函数
    FrameBuffer编程二(简单的程序上)
    FrameBuffer编程一(数据结构)
    mmap函数介绍
  • 原文地址:https://www.cnblogs.com/hesper/p/10738987.html
Copyright © 2011-2022 走看看