iOS线程锁

简介: iOS线程锁

一:十种线程锁

我们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题,这时候就需要我们保证每次只有一个线程访问这一块资源,锁 应运而生。

这里顺便提一下,上锁的两种方式trylock和lock使用场景:

当前线程锁失败,也可以继续其它任务,用 trylock 合适

当前线程只有锁成功后,才会做一些有意义的工作,那就 lock,没必要轮询 trylock

以下是十种线程锁所用时间:

1、OSSpinLock (自旋锁)

测试中效率最高的锁, 不过经YYKit作者确认, OSSpinLock已经不再线程安全,OSSpinLock有潜在的优先级反转问题

需要导入头文件
#import <libkern/OSAtomic.h>
// 初始化
OSSpinLock spinLock = OS_SPINLOCK_INIT;
// 加锁
OSSpinLockLock(&spinLock);
// 解锁
OSSpinLockUnlock(&spinLock);
// 尝试加锁,可以加锁则立即加锁并返回 YES,反之返回 NO
OSSpinLockTry(&spinLock)
/*
注:苹果爸爸已经在iOS10.0以后废弃了这种锁机制,使用os_unfair_lock 替换,
顾名思义能够保证不同优先级的线程申请锁的时候不会发生优先级反转问题.
*/

2、os_unfair_lock(互斥锁)

需要导入头文件
#import <os/lock.h>
// 初始化
os_unfair_lock unfair_lock = OS_UNFAIR_LOCK_INIT;
// 加锁
os_unfair_lock_lock(&unfair_lock);
// 解锁
os_unfair_lock_unlock(&unfair_lock);
// 尝试加锁,可以加锁则立即加锁并返回 YES,反之返回 NO
os_unfair_lock_trylock(&unfair_lock);
/*
注:解决不同优先级的线程申请锁的时候不会发生优先级反转问题.
不过相对于 OSSpinLock , os_unfair_lock性能方面减弱了许多.
*/

3、dispatch_semaphore (信号量)

// 初始化
dispatch_semaphore_t semaphore_t = dispatch_semaphore_create(1);
// 加锁
dispatch_semaphore_wait(semaphore_t,DISPATCH_TIME_FOREVER);
// 解锁
dispatch_semaphore_signal(semaphore_t);
/*
注: dispatch_semaphore  其他两个功能
1.还可以起到阻塞线程的作用.
2.可以实现定时器功能,这里不做过多介绍.
*/

二:锁的类型

1、自旋锁

OSSpinLock 就是典型的自旋锁

自旋锁的特点是在没有获取到锁时既锁已经被添加,还没有被解开时. OSSpinLock处于忙等状态,一直占用CPU资源,类似如下伪代码:

while(锁没解开);

关于优先级反转问题

由于线程调度,每条线程的分配时间权重不一样,当权重小的线程先进入OSSpinLock优先加锁,当权重大的线程再来访问,就阻塞在这,可能权重大的线程会一直分配到cpu所以一直会进来,但是因为有锁,只能等待,权重小的线程得不到cpu资源分配,所以不会解锁,造成一定程度的死锁.

2、互斥锁

os_unfair_lock 、pthread_mutex是典型的互斥锁,在没有获取到锁时既锁已经被添加,还没有被解开时.

它们都会让当前线程进入休眠状态既不占用CPU资源,但是为什么,互斥锁比自旋锁的效率低呢,是因为休眠,以及唤醒休眠,比忙等更加消耗CPU资源.

NSLock 封装的pthread_mutex的PTHREAD_MUTEX_NORMAL 模式

NSRecursiveLock 封装的pthread_mutex的PTHREAD_MUTEX_RECURSIVE 模式

3、条件锁

在一定条件下,让其等待休眠,并放开锁,等接收到信号或者广播,会从新唤起线程,并重新加锁.

pthread_cond_wait(&_cond, &_mutex);
// 信号
pthread_cond_signal(&_cond);
// 广播
pthread_cond_broadcast(&_cond);
像NSCondition封装了pthread_mutex的以上几个函数,NSConditionLock封装了NSCondition

4、递归锁

递归锁的主要意思是,同一条线程可以加多把锁.什么意思呢,就是相同的线程访问一段代码,如果是加锁的可以继续加锁,继续往下走,不同线程来访问这段代码时,发现有锁要等待所有锁解开之后才可以继续往下走.

NSRecursiveLock 封装的pthread_mutex 的PTHREAD_MUTEX_RECURSIVE模式

目录
相关文章
|
3月前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
47 2
|
3月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
2月前
|
运维 API 计算机视觉
深度解密协程锁、信号量以及线程锁的实现原理
深度解密协程锁、信号量以及线程锁的实现原理
41 1
|
2月前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
41 0
|
2月前
|
Java API
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
38 0
|
2月前
|
安全 Java 程序员
【多线程-从零开始-肆】线程安全、加锁和死锁
【多线程-从零开始-肆】线程安全、加锁和死锁
47 0
|
2月前
|
安全 Linux
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
|
3月前
|
存储 算法 Java
关于python3的一些理解(装饰器、垃圾回收、进程线程协程、全局解释器锁等)
该文章深入探讨了Python3中的多个重要概念,包括装饰器的工作原理、垃圾回收机制、进程与线程的区别及全局解释器锁(GIL)的影响等,并提供了详细的解释与示例代码。
35 0
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
51 1
C++ 多线程之初识多线程
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
21 3