iOS开发中的各种锁
- OSSpinlock
- os_unfair_lock
- dispath_semaphore
- pthread_mutex
- pthread_rwlock
- pthread_cond
- NSCondition
- NSConditionLock
- NSLock
- NSCuresiveLock
- @synchronized
锁儿们
自旋锁
性能最高的锁。
原理:如果共享数据被其他线程加锁,那么当前线程会一死循环的方式等待解锁,一旦访问的资源被解锁,则等待线程就会立即执行。
由此可见,如果共享资源被锁了,线程不会进入等待状态,他会循环的锁的状态,所以实际上会消耗CPU的资源。
也就是说,在较为耗时的操作,并不适合使用自旋锁。比如:读写硬盘这种就不适合用自旋锁。而读写缓存,和内存可以是用自旋锁。
为什么自选锁的性能会比较高:
主动出让时间片(也就是互斥的做法)会导致操作系统切换到另外一个县城,这种上下文切换会通常占用10微妙左右的时间,来回调度起码就是两次。所以如果等待时间特别短,可能只有几个微妙,那么自旋锁的忙等明显要比互斥锁的休眠更加高效。
iOS的自旋锁:
- OSSpinlock:iOS10以后被废弃,因其不安全,有可能造成死锁。
- os_unfair_lock:iOS之后才可以使用,代替
OSSpinlock
的方案
在iOS
中线程优先级有五个(QoS):
- QOS_CLASS_BACKGROUND
- QOS_CLASS_UTILITY
- QOS_CLASS_UTILITY
- QOS_CLASS_USER_INITATED
- QOS_CLASS_USER_INTERACTIVE
由上到下是低到高。
GCD是四个级别:
- Dispath_QUEUE_PRIORITY_HIGH
相当于 QOS_CLASS_USER_INITATED
- Dispath_QUEUE_PRIORITY_DEFAULT
相当于 QOS_CLASS_DEFAULT
- Dispath_QUEUE_PRIORITY_LOW
相当于 QOS_CLASS_UTILITY
- Dispath_QUEUE_PRIORITY_BACKGROUND
相当于 QOS_CLASS_BACKGROUND
OSSpinlock可能造成死锁的原因:
有可能在优先级比较低的线程里对共享资源进行加锁了,然后高优先级的线程抢占了低优先级的调用CPU时间,导致高优先级的线程一直在等待低优先级的线程释放锁,然而低优先级根本没法抢占高优先级的CPU时间。
这种情况我们称作 优先级倒转。
互斥锁:
原理:如果共享资源已经有其他线程加锁了,线程会进入休眠状态等待锁。一旦被访问的资源被解锁,则等待资源的线程会被唤醒。
互斥锁不会同时被两个不同的线程同时得到。也就是如果是当前线程加的锁,别的线程是没有办法获取这个锁,也就没有办法对他进行解锁。
iOS中的互斥锁
- pthread_mutex
- NSLock
- NSCuresiveLock
- @synchronized
互斥锁属性:
- PTHREAD_MUTEX_NORMAL 0:普通锁
当一个线程获得锁以后,其余请求锁的线程讲形成一个等待队列,并在解锁后按优先级获得锁。
- PTHREAD_MUTEX_ERRORCHECK 1:检错锁
如果同一个线程多次请求同一个锁,则返回错误,否则按照
PTHREAD_MUTEX_NORMAL
逻辑来
- PTHREAD_MUTEX_RECURSIVE 2:嵌套锁
允许同一个线程对同一个锁获得多次,也可以解锁多次。如果多个线程请求,也是需要等解锁之后才能竞争。
- PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
读写锁
原理:允许多个线程同时对同一个数据进行读操作,而只允许一个线程进行写操作。这是因为读操作不会改变数据的内容,是安全的;而写操作会改变数据的内容,是不安全的。
iOS中的读写锁
- pthread_rwlock_t
条件锁
原理:进入等待,直到满足条件后执行。
iOS中的条件锁
- NSCondition
- NSConditionLock
- pthread_cond
信号量加锁
原理:多元信号量允许多个线程访问同一个资源,多元信号量简称信号量(Semaphore),对于允许多个线程并发访问的资源,这是一个很好的选择。一个初始值为N的信号量允许N个线程并发访问。
其实严格的来说信号量不能算锁。
而且如果信号量设置为1,我们可以把它当作互斥锁来用
iOS中的信号量加锁
- dispatch_semaphore
网友评论