线程:markdown
- 线程是进程的基本执行单元,一个进程的全部任务都在线程中执行
- 进程要想执行任务,必须得有线程,进程至少要有一条线程
- 程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程
进程:多线程
- 进程是指在系统中正在运行的一个应用程序
- 每一个进程之间是独立的,每一个进程均运行在其专用的且受保护的内存空间内
- 经过“活动监视器”能够查看 Mac 系统中所开启的进程
地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。 资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,可是进程之间的 资源是独立的。并发
- 一个进程崩溃后,在保护模式下不会对其余进程产生影响,可是一个线程崩溃整个进程都死掉。因此多进程要比多线程健壮。
- 进程切换时,消耗的资源大,效率高。因此涉及到频繁的切换时,使用线程要好于进程。一样若是要求同时进行而且又要共享某些变量的并发操做,只能用线程不能用进程
- 执行过程:每一个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。可是 线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
- 线程是处理器调度的基本单位,可是进程不是。
- 线程没有地址空间,线程包含在进程地址空间中
优势:性能
- 能适当提升程序的执行效率
- 能适当提升资源的利用率(CPU,内存)
- 线程上的任务执行完成后,线程会自动销毁
缺点atom
- 开启线程须要占用必定的内存空间(默认状况下,每个线程都占 512 KB)
- 若是开启大量的线程,会占用大量的内存空间,下降程序的性能
- 线程越多,CPU 在调用线程上的开销就越大
* 程序设计更加复杂,好比线程间的通讯、多线程的数据共享spa
时间片的概念:CPU在多个任务直接进行快速的切换,这个时间间隔就是时间片线程
* (单核CPU)同一时间,CPU 只能处理 1 个线程 * 换言之,同一时间只有 1 个线程在执行设计
* 多线程同时执行: * 是 CPU 快速的在多个线程之间的切换3d
* 若是线程数很是多code
* 每一个线程被调度的次数会下降,线程的执行效率下降
__bridge
只作类型转换,可是不修改对象(内存)管理权;__bridge_retained
(也可使用CFBridgingRetain
)将Objective-C的对象转换为 Core Foundation的对象,同时将对象(内存)的管理权交给咱们,后续须要使用 CFRelease或者相关方法来释放对象;__bridge_transfer
(也可使用CFBridgingRelease
)将Core Foundation
的对象 转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。这四种拒绝策略均实现的RejectedExecutionHandler接口
在看优先级反转前先了解什么是IO密集型线程和CPU密集型线程。
IO密集型线程比CPU密集型线程更容易获得优先级提高。
特殊场景下,当多个优先级都比较高的CPU 密集型线程霸占了全部 CPU 资源,而此时优先级较低的 IO 密集型线程将持续等待,产生线程饿死的现象。固然,为了不线程饿死,CPU会发挥调度做用去逐步提升被“冷落”线程的优先级(提升优先级不必定就会执行,有几率的问题),IO 密集型线程一般状况下比 CPU 密集型线程更容易获取到优先级提高。
在咱们使用多线程的过程当中会遇到一种现象,就是资源抢夺。
例如多窗口售票这个案例,假设如今有 1000 张票,窗口 1 售卖了一张还剩 999 张,可是窗口 2 并不能同步知道剩余票数,因此仍是按照 1000 张去售票,这种状况就会出现问题。这个时候咱们就须要借助加锁操做来解决这种问题。这里咱们介绍两种锁,自旋锁与互斥锁。
互斥锁:
互斥锁参数:
自旋锁:
互斥锁与自旋锁的区别:
atomic:
atomic
是原子属性,是为多线程开发准备的,是默认属性!setter
方法中,增长了锁(自旋锁),可以保证同一时间,只有一条线程对属性进行写
操做nonatomic:
nonatomic
是非原子属性下面咱们来看一下 atomic
的底层实现:
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
if (offset == 0) {
object_setClass(self, newValue);
return;
}
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:nil];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:nil];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
// 判断是不是 atomic 标识,是的话就添加锁操做
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
oldValue = *slot;
*slot = newValue;
slotlock.unlock();
}
objc_release(oldValue);
}
复制代码
在源码中咱们能够看到 atomic
其实就是一个标识,底层根据 atomic
标识来判断是否加锁。