• iOS - 多线程-读写安全


    iOS - 多线程-读写安全

    假设有一个文件,A线程进行读取操作,B线程进行写入操作,那是非常危险的事情,会造成数据错乱

    此时可能会对其进行加锁来保证线程同步

    虽然加锁可以解决问题,但是针对该场景,操作其实不会影响原数据,因此是可以允许多线程同时读,以提高性能

    其实就是实现多读单写的操作

    1. 多读单写

    1.1 场景

    • 同一时间,只能1个线程进行的操作
    • 同一时间,允许多个线程进行的操作
    • 同意时间,不允许即有的操作,又有的操作

    1.2 实现方案

    1.2.1 pthread_rwlock:读写锁
    • 等待锁的线程会进入休眠

    1.2.1.1 示例
    #import "ViewController.h"
    #import 
    
    @interface ViewController ()
    
    @property (nonatomic, assign) pthread_rwlock_t lock;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.title = @"pthread_rwlock_t";
        
        // 初始化锁
        pthread_rwlock_init(&_lock, NULL);
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        for (int i = 0; i < 5; i++) {
            dispatch_async(queue, ^{
                [self read];
            });
            
            dispatch_async(queue, ^{
                [self read];
            });
            
            dispatch_async(queue, ^{
                [self write];
            });
            
            dispatch_async(queue, ^{
                [self write];
            });
        }
    }
    
    - (void)read {
        pthread_rwlock_rdlock(&_lock);
        
        sleep(1);
        NSLog(@"%s", __func__);
        
        pthread_rwlock_unlock(&_lock);
    }
    
    - (void)write {
        pthread_rwlock_wrlock(&_lock);
        
        sleep(1);
        NSLog(@"%s", __func__);
        
        pthread_rwlock_unlock(&_lock);
    }
    
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    执行结果:

    可以看到,的操作是连续的,的操作是间隔的

    1.2.2 dispatch_barrier_async:异步栅栏调用
    • 这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的
    • 如果传入的是一个串行或是一个全局并发队列,那这个函数便等同于dispatch_async函数的效果

    可以理解为,每个操作都使用栅栏将其与其它线程隔离开

    1.2.2.1 示例
    #import "ViewController_barrier.h"
    
    @interface ViewController_barrier ()
    
    @property (nonatomic, strong) dispatch_queue_t queue;
    
    @end
    
    @implementation ViewController_barrier
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.title = @"dispatch_barrier_sync";
        
        self.queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        for (int i = 0; i < 5; i++) {
            [self read];
            
            [self read];
            
            [self write];
            
            [self write];
        }
    }
    
    - (void)read {
        dispatch_async(self.queue, ^{
            sleep(1);
            NSLog(@"%s", __func__);
        });
    }
    
    - (void)write {
        dispatch_barrier_sync(self.queue, ^{
            sleep(1);
            NSLog(@"%s", __func__);
        });
    }
    
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    打印结果:

    同样达到多读单写的效果

    @oubijiexi

  • 相关阅读:
    01、Python 安装 ,Pycharm 安装
    读《mysql是怎样运行的》有感
    1.DApp-做一个DApp需要学习什么
    卸载MIUI13内置百度输入法
    华为云桌面Workspace,让你的办公更加舒适惬意
    随机数发生器设计(四)
    pyqt QPlainTextEdit 中捕获回车
    基于Python实现的快递管理系统源码+数据库,采用PyQt6实现GUI界面
    【NodeJs-5天学习】第二天篇④ ——项目模块化
    Java栈和队列的实现
  • 原文地址:https://blog.csdn.net/sharp521/article/details/138154359