目录
进程线程的相关概念
一、进程与线程介绍
1、进程
系统中正在运行的一个应用程序
每个进程独立
每个进程运行在自己独立的内存空间内
2、线程
进程的基本执行单元
一个进程所有的任务都在线程中执行
进程至少要有一条线程
同进程中的不同线程可以共享数据,但拥有自己的栈空间和独立的执行序列
3、根本区别
进程是操作系统进行资源分配的基本单位,线程是操作系统进行任务调度的基本单位
二、线程相关
如果线程数非常多,CPU会在N个线程之间切换,消耗大量的CPU,每个线程被调度的次数会降低,线程的执行效率降低
1、多线程的优点
能适当提高程序的执行效率
能适当提高资源的利用率(CPU,内存)
线程上的任务执行完成后,线程会自动销毁
2、多线程的缺点
开启线程需要占用一定的内存空间(默认情况下,每一个线程都占 512 KB)
如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,CPU 在调用线程上的开销就越大
程序设计更加复杂,比如线程间的通信、多线程的数据共享
3、线程的状态
创建线程 - 就绪 - 运行 - 阻塞 - 死亡
4、为什么打印出的线程号不连续,且有重复?
创建线程时会去线程池内查看是否有已经创建好的线程并且线程没有在执行任务。如果有就取出进行使用。
线程创建需要时间和消耗资源。这样可以时间和资源。
GCD的线程池中有64条线程
5、GCD
会自动利用CPU的多核
会自动管理线程的生命周期
程序员只需要告诉GCD执行什么样的任务,不需要编写任何线程管理的代码
6、队列与线程
队列与线程没有任何关系,队列只是用来存储任务的,没有能力去调度任务
队列的类型:串行队列 和 并发队列
7、同步与异步
同步:等任务执行完之后才会返回,不会开起新的线程
异步:不用等任务执行就立即返回,开起新的线程
多线程
一、单例的原理
二、栅栏函数
为什么要对全局并发队列无效
因为系统也在使用这个队列
如果栅栏住了系统的调用就不合理了
三、groupenter和groupleave
四、dispatch_group_async
五、信号量
能够控制并发数量
信号量释放的时候,信号量的值如果小于创建时的值,就会崩溃
wait 和 signal 要成对出现
六、dispatch_source
创建source
给source添加监听事件
dispatch_resume(self.source);
恢复
dispatch_suspend(self.source);
挂起
dispatch_source_cancel(self.source);
取消
锁
一、原子属性和os_unfair_lock
锁是为了解决多线程的中线程安全问题
1、automatic
self.count –
既有set 方法又有get方法
原子属性只能保证set或者get单个方法的线程安全,也就是说对set方法加了锁1,对get方法加了锁2.
当同时调用set和get时线程是不安全的,并不能保证绝对的线程安全
2、锁的种类
自旋锁:忙等
线程不会休眠
不会有线程的调度开销
效率较高
互斥锁:闲等
线程会休眠,CPU会去调度其它的线程
会有线程的调度开销
递归锁属于互斥锁
os_unfair_lock是互斥锁
读写锁
二、NSCondition
1、NSLock
底层是对pthread的封装
pthread支持递归,但NSLock阉割了这个功能
2、NSCondition
lock
unlock
wait
signal
三、NSRecursiveLock和NS
锁:同一时刻只能被一条线程拥有
但递归锁有一个特性:同一时刻能被多条线程拥有
所以递归锁只能在同一条线程下使用
多条线程下使用递归锁会发生死锁
四、读写锁
- (NSString *)lg_read {
// 异步读取
__block NSString *ret;
//此处用同步,是因为有返回值。用异步返回值就不准确了
dispatch_sync(self.iQueue, ^{
// 读取的代码
ret = self.dataDic[@"name"];
});
NSLog(@"%@",ret);
return ret;
}
- (void)lg_write: (NSString *)name {
// 写操作
//用栅栏函数保证读写互斥
dispatch_barrier_async(self.iQueue, ^{
[self.dataDic setObject:name forKey:@"name"];
});
}
- (IBAction)moreReadSigleWrite:(id)sender {
for (int i = 0; i<10; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (i == 5) {
[self lg_write:[NSString stringWithFormat:@"%d-name" ,i]];
} else {
[self lg_read];
}
});
}
}
行者常至,为者常成!