一.线程与内存
1.一个线程内核空间:1kb
2.一个线程栈空间:主线程 1M,子线程 512KB
二.线程与时间
1.创建时间:4~5毫秒
2.启动时间:平均29毫秒
3.总结:开启多个线程非常耗时间
4.GCD上线 64个
三.对比
1.GCD
(1)简单,方便
(2)可以设置栅栏
(3) 不用手动管理
2.NSOperation
(1)面向对象(国外使用较多)
(2)优先级
(3)可以取消,挂起
(4)可以手动管理线程(挂起,取消)
(5)wait
(6)多核安全
3.NSThread
(1).最大程度控制
(2).优先级
(3)麻烦,需要自己枷锁
四. 原子属性一定安全?
一下是我自己写的例子
{
p.name = "张三"
| B线程(*2)
p.name = "李四"
| A线程(*1)
print(p.name)
}
不安全步骤:
(1)语境:A,B 线程同时 执行这个代码块
(2)A线程走到 *1 处挂起,执行B线程
(3)B线程 走到 *2 处挂起,执行 A线程
(4)这个时候A线程打印 出来的是 "张三",但是我们期望的却是"李四",线程不安全
五.保证线程安全
(1) synchronized
@synchronized (xxx) {
p.name = "张三"
p.name = "李四"
print(p.name)
}
(2)NSLock
(3)NSRecursiveLock 允许锁定好多次,适用场景:多个方法同一个锁同步。
- (void)a1{
[self.lock lock];
[self a2];
[self.lock unlock];
}
- (void)a2{
[self.lock lock];
// code
[self.lock unlock];
}
(4)NSCondition
作用:解决生产者消费这问题。大概用法:当两个线程适用同一个NSCondition加锁时,比如A线程 生产完一个产品,signal、unlock后,会唤醒B线程进行消费。
六.并发读写问题
(1)atomic 只允许一条线程进行读或写,不允许多个线程同时访问这个属性,弊端:有时候需要允许并行读,不允许并行改,这个时候会严重影响性能
(2)高吞吐量并发安全读写:本质上允许并行读取,写入互斥.伪代码
- (id)getMethod{
__block id rv = nil
dispatch_async(self.queue, ^{
nil = @"";
})
return nil;
}
- (void)setMethod:(id)obj{
dispatch_barrier_async(self.queue, ^{
//code
})
}
七 多参初始化器 initWithParam :(id)Param :(id)Param :(id)Param :(id)Param :(id)Param .....N个参数
问题:参数太多,向下兼容问题,加入再多一个,还要再加。
解决方案:生成器模式
@implementation User
+ (instancetype)userWithBlock:(void(^)Builder)block{
Builder *b = [Builder new];
block(b); -> //(1) 用户 设置 b的属性,相当于传入初始化值
return [b build];
}
- (instancetype) initWithBuilder:(Builder *)b{
self.x = b.x //(4)
.......
}
@implementation Builder
- (User *) build{
return [[User alloc]initWithBuilder:self];//(3)
}
如何使用(获取User),已注明这段代码调用顺序
User *u = [User userWithBlock:^(b){
b.x = @"";//赋值 (2)
}];
(1)调用类方法
(2)让用户传值
(3)调用Builder方法 生成User
(4)User 根据Builder 创建自己对象
八.冰棒不可变
总而言之:前期可变,后期不可变。伪代码
- (void)setxxx:(id)obj{
if(!bukebian){
_x = obj;
}
}
九 函数响应式编程,自行网上找资料,这里只是告诉你有这个东西,什么用,详细用法github。
十 死锁
1.主线程徒步
2.同一个线程多个同步。
网友评论