iOS总结

iOS 线程锁

2020-05-12  本文已影响0人  赵_df7e

一般情况下,我们定义属性的时候都是这样定义的:

@property (nonatomic, copy) NSString *string1;
@property (nonatomic, strong) NSMutableString *string2;

copystrong的区别就不在这里多说了,主要来看下这个nonatomic以及atomic

nonatomic & atomic

atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。这里是指系统自动生成的 getter/setter 方法。如果自己重写 getter/setter方法,那atomic/nonatomic只起提示作用

{lock}
if (property != newValue) { 
    [property release]; 
    property = [newValue retain]; 
}
{unlock}

于是引出了本篇的话题:线程锁

线程锁

多线程编程中,应该尽量避免资源在线程之间共享,以减少线程间的相互作用。 但是总是有多个线程相互干扰的情况(如多个线程访问一个资源)。在线程必须交互的情况下,就需要一些同步工具,来确保当它们交互的时候是安全的。

简单来说:我们引入锁的目的是为了线程安全。

image

找到一张关于线程锁性能的比较图片,如图所示

性能最好的是OSSpinLock(据说是不安全的的,详情请看ibireme大神的不再安全的 OSSpinLock)

我们一起来看下在iOS开发中常用的几种锁

1. @synchronized

推荐文章:
Peak大神正确使用多线程同步锁@synchronized()
关于 @synchronized,这儿比你想知道的还要多
@synchronized 结构所做的事情跟锁(lock)类似:它防止不同的线程同时执行同一段代码。@synchronized是几种iOS多线程同步机制中最慢的一个,同时也是最方便的一个。苹果建立@synchronized的初衷就是方便开发者快速的实现代码同步,语法如下:

@synchronized(object) {
  //code
}

Peak大神在文章中提醒我们:

@synchronized也经常用来实现单例,用的更多的还是GCD中的一次函数dispatch_once,关于@synchronized和dispatch_once的性能比较,有兴趣的童鞋们可以看这里

2. NS系列锁

NS系列锁指的是NSLockNSConditionNSConditionLockNSRecursiveLock,之所以把这几个放在一起,是因为它们都遵守NSLocking协议,就俩方法,加锁解锁,so easy!

@protocol NSLocking
- (void)lock;
- (void)unlock;
@end

2.1 NSLock 线程锁

看下NSLock 的API,嗯,很少也很简单:

@interface NSLock : NSObject <NSLocking> {
@private
    void *_priv;
}
- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

方法说明:
trylock:能加锁返回 YES 并执行加锁操作,相当于 lock,反之返回 NO
lockBeforeDate:这个方法表示会在传入的时间内尝试加锁,若能加锁则执行加锁操作并返回 YES,反之返回 NO。

2.2 NSConditionLock 条件锁

condition:条件,顾名思义NSConditionLock就是有条件的加锁,继续来看API

@interface NSConditionLock : NSObject <NSLocking> {
@private
    void *_priv;
}

- (instancetype)initWithCondition:(NSInteger)condition NS_DESIGNATED_INITIALIZER;

@property (readonly) NSInteger condition;
- (void)lockWhenCondition:(NSInteger)condition;
- (BOOL)tryLock;
- (BOOL)tryLockWhenCondition:(NSInteger)condition;
- (void)unlockWithCondition:(NSInteger)condition;
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

比较了一下,貌似跟NSLock差不多,只是加了个condition,还是NSInteger类型的,感觉只要把这个参数搞明白就差不多了。
condition我们可以理解为一个条件标示,看下创建方法:initWithCondition:创建的时候传入一个条件标识,之后如果使用创建好的锁,必须传入对应的标识才能完成对应的lock和unlock操作

2.3 NSRecursiveLock 递归锁
@interface NSRecursiveLock : NSObject <NSLocking> {
@private
    void *_priv;
}

- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

2.4 NSCondition 断言
@interface NSCondition : NSObject <NSLocking> {
@private
    void *_priv;
}

- (void)wait;
- (BOOL)waitUntilDate:(NSDate *)limit;
- (void)signal;
- (void)broadcast;

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

3. dispatch_semaphore 信号量实现加锁(GCD)

之前写过一篇dispatch_semaphore信号量的文章,麻烦大家手动移驾过去。

我自己测试的线程锁的性能如下:

image

推荐文章(排名不分先后):
(ibireme大神的不再安全的 OSSpinLock)
https://www.jianshu.com/p/1e59f0970bf5

关于递归锁与非递归锁,平常接触比较少,有兴趣的童鞋可以了解一下:https://blog.csdn.net/zouxinfox/article/details/5838861

原文链接:https://www.jianshu.com/p/b5c63d7c36da

上一篇 下一篇

猜你喜欢

热点阅读