本文博主带领大家一起学习一下iOS开发中的锁。
为什么用到锁?
当一个线程访问数据的时候,其他的线程不能对其进行访问,直到该线程访问完毕。即确保线程安全。比如:iOS中的读写文件,当一个线程在写文件时,如果另一个线程去读或者去写,这样都会导致数据紊乱。为了线程安全,我们使用锁的机制来确保,同一时刻只有同一个线程来对一个数据源进行访问。
iOS中都用什么锁?
互斥锁
1.NSLock
2.pthread_mutex
3.@synchronized
4.os_unfair_lock
是一种用于多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读写的机制。该目的通过将代码切片成一个一个的临界区而达成。
自旋锁
1.OSSpinLock
是用于多线程同步的一种锁,线程反复检查锁变量是否可用。由于线程在这一过程中保持执行,因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的。
自旋锁和互斥锁的区别对比:
自旋锁的效率高于互斥锁
相同点:
都能保证同一时间只有一个线程访问共享资源,都能保证线程安全。
不同点:
互斥锁:如果共享数据已经有其他线程加锁了,线程会进入休眠状态等待锁,一旦被访问的资源被解锁,则等待资源的线程会被唤醒。
自旋锁:如果共享数据已经有其他线程加锁了,线程会以死循环的方式等待锁,一旦被访问的资源被解锁,则等待资源的线程会立即执行。
递归锁
1.NSRecursiveLock:
2.pthread_mutex
递归锁有一个特点,就是同一个线程可以加锁N次而不会引发死锁。
条件锁
1. NSCondition:
2.NSConditionLock:
就是条件变量,当进程的某些资源要求不满足时就进入休眠,也就是锁住了。当资源被分配到了,条件锁打开,进程继续运行。
读写锁
pthread_rwlock
读写锁通常用互斥锁、条件变量、信号量实现。
是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁) 用于解决多线程对公共资源读写问题。读操作可并发重入,写操作是互斥的。
信号量
1. dispatch_semaphore
遵循NSLocking协议,使用的时候同样是lock,unlock加解锁,wait是傻等,waitUntilDate:方法是等一会,都会阻塞掉线程,signal是唤起一个在等待的线程,broadcast是广播全部唤起。
1.NSLock
NSLock实现了最基本的互斥锁,使用时需要遵循 NSLocking协议,通过lock和unlock来进行锁定和解锁。
例子如下:在线程A 调用unlock方法之前,另一个线程B调用了同一锁对象的lock方法。那么,线程B只有等待。直到线程A调用了unlock。
实际项目中:NSLock在AFNetworking的AFURLSessionManager.m中应用如下:
2.@synchronized
实际项目中:AFNetworking中 isNetworkActivityOccurring属性的getter方法
3.dispatch_semaphore
dispatch_semaphore是GCD用来同步的一种方式,与他相关的共有三个函数,分别是:
dispatch_semaphore_create(创建一个semaphore),dispatch_semaphore_signal(发送一个信号),dispatch_semaphore_wait(等待信号)。
dispatch_semaphore在YYKit中的YYThreadSafeArray.m有所应用
这个例子中,为线程设置了最大等待时间12秒,所以当上面的线程sleep10秒的时候,下面的线程仍然要等待。4.phtread_mutex
phtread_mutex实现互斥锁比递归锁效率高。
在YYKit的YYMemoryCach中可以看到
5.pthread_rwlock
//加读锁
pthread_rwlock_rdlock(&rwlock);
//解锁
pthread_rwlock_unlock(&rwlock);
//加写锁
pthread_rwlock_wrlock(&rwlock);
//解锁
pthread_rwlock_unlock(&rwlock);
6.NSCondition
代码分析:condition 进入到判断条件中,当products == 0 的时候,condition 调用wait 时当前线程处于等待状态;其他线程开始访问products,当NSObject 创建完成并加入到products时,cpu发出single的信号时,处于等待的线程被唤醒,开始执行[products removeObjectAtIndex:0];
7.OSSpinLock
首先要提的是OSSpinLock已经出现了BUG,导致并不能完全保证是线程安全的。
8.os_unfair_lock
os_unfair_lock 是苹果官方推荐的替换OSSpinLock的方案,它是一个互斥锁,但是它在iOS10.0以上的系统才可以调用。os_unfair_lock是一种互斥锁,它不会向自旋锁那样忙等,而是等待线程会休眠。
9.NSConditionLock
NSConditionLock定义了一个可以指定条件的互斥锁,用于线程之间的互斥与同步,性能较低。
10.NSRecursiveLock
NSRecursiveLock在YYKit中YYWebImageOperation.m中有用到