iOS底层学习-day-23

前言-OC-多线程篇

我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。

atomic

  • 例子:
#import <Foundation/Foundation.h>

@interface MJPerson : NSObject

@property (nonatomic, assign) int age;
@property (atomic, copy) NSString *name;
@property (atomic, strong) NSMutableArray *data;//atomic 会加上加锁和解锁操作

@end

/*
 nonatomic和atomic
 atom:原子,不可再分割的单位
 atomic:原子性
 
 给属性加上atomic修饰,可以保证属性的setter和getter都是原子性操作,也就是保证setter和gette内部是线程同步的
 
 // 加锁,原子属性就是把三行代码变成一句,变成一个整体,并不是说线程同步是安全的,只是说setter和getter内部是加锁安全的而已
 int a = 10;
 int b = 20;
 int c = a + b;
 // 解锁
 
 */

NSMutableArray *array = p.data;//p.data只有这个安全的
// 加锁
[array addObject:@"1"];
[array addObject:@"2"];
[array addObject:@"3"];
// 解锁

读写安全

  • 思考如何实现以下场景

    • 同一时间,只能有1个线程进行写的操作
    • 同一时间,允许有多个线程进行读的操作
    • 同一时间,不允许既有写的操作,又有读的操作
  • 上面的场景就是典型的“多读单写”,经常用于文件等数据的读写操作,iOS中的实现方案有

    • pthread_rwlock:读写锁
    • dispatch_barrier_async:异步栅栏调用
  • pthread_rwlock - 读写锁
    在这里插入图片描述

#import "ViewController.h"
#import <pthread.h>

@interface ViewController ()
@property (assign, nonatomic) pthread_rwlock_t lock;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化锁
    pthread_rwlock_init(&_lock, NULL);
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            [self read];
        });
        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);
}

- (void)dealloc {
    pthread_rwlock_destroy(&_lock);
}


@end
  • dispatch_barrier_async - 异步栅栏调用
    • 这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的
    • 如果传入的是一个串行或是一个全局的并发队列,那这个函数便等同于dispatch_async函数的效果
      在这里插入图片描述
//就是一定要自己创建DISPATCH_QUEUE_CONCURRENT,并发队列
#import "ViewController.h"

@interface ViewController ()

@property (strong, nonatomic) dispatch_queue_t queue;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i < 10; i++) {
        dispatch_async(self.queue, ^{
            [self read];
        });
        
        dispatch_async(self.queue, ^{
            [self read];
        });
        
        dispatch_async(self.queue, ^{
            [self read];
        });
        
        dispatch_barrier_async(self.queue, ^{
            [self write];
        });
    }
}

- (void)read {
    sleep(1);
    NSLog(@"read");
}

- (void)write {
    sleep(1);
    NSLog(@"write");
}

@end

NSProxy

  • NSProxy 和NSObject同一级别,专门用来做消息转发的
  • 例子1: timer的释放,是有问题的self->target->self所以会被强引用
#import "ViewController.h"

@interface ViewController ()

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    __weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        [weakSelf timerTest];
    }];
}

- (void)timerTest {
    NSLog(@"%s", __func__);
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    [self.timer invalidate];
}

@end
  • 例子2: - 例子1问题解决
  • MJProxy.h

#import <Foundation/Foundation.h>

@interface MJProxy : NSProxy

+ (instancetype)proxyWithTarget:(id)target;
@property (weak, nonatomic) id target;

@end
  • MJProxy.m
#import "MJProxy.h"

@implementation MJProxy

+ (instancetype)proxyWithTarget:(id)target {
    // NSProxy对象不需要调用init,因为它本来就没有init方法
    MJProxy *proxy = [MJProxy alloc];
    proxy.target = target;
    return proxy;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}

@end
  • 使用
#import "ViewController.h"
#import "MJProxy.h"

@interface ViewController ()

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[MJProxy proxyWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
}

- (void)timerTest {
    NSLog(@"%s", __func__);
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    [self.timer invalidate];
}

@end
发布了31 篇原创文章 · 获赞 0 · 访问量 945

猜你喜欢

转载自blog.csdn.net/weixin_41732253/article/details/103999587