一些相关总结(同步、异步、并行、串行概念,GCD、NSOperation对比)
1、进程与线程概念
2、多线程-GCD
3、多线程-NSOperation
4、多线程-NSThread
5、队列概念
6、多线程面试题java
GCD --> iOS 4.0
(1)将任务(block)添加到队列(串行/并发(全局)),指定执行任务的方法(同步(阻塞)/异步)
(2)拿到 dispatch_get_main_queue()。 线程间通讯
(3)NSOperation没法作到一次性执行、延迟执行、调度组(op相对复杂)
(4)提供了更多的控制能力以及操做队列中所不能使用的底层函数ios
NSOperation ----> iOS 2.0 (后来苹果改造了NSOperation的底层)
(1)将操做(异步执行)添加到队列(并发/全局)
(2)[NSOperationQueue mainQueue] 主队列。 任务添加到主队列, 就会在主线程执行
(3)提供了一些GCD很差实现的,”最大并发数“、依赖关系、暂停/继续 --- 挂起、取消全部的任务git
对比:
(1)GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装
(2)GCD只支持FIFO的队列,NSOperationQueue能够很方便的调整执行顺序、设置最大并发数量 (FIFO 就是先进先出)
(3)NSOperationQueue能够很轻松的在Operation间设置依赖关系,而GCD须要写不少代码才能实现
(4)NSOperationQueue支持KVO(键值观察者),能够监听operation是否正在执行 (isExecuted)、是否结束(isFinished)、是否取消(isCanceld)
(5)GCD的执行速度比NSOperationQueue快(封装GCD,更高层的东西,性能很差,由于还要转化成GCD)快程序员
在项目何时选择使用GCD,何时选择NSOperation?
· NSOperation:
任务之间有依赖\或者要监放任务的执行状况
项目中使用的优势是它是对线程的高度抽象,会使程序结构更好,子类化NSOperation的设计思路具备面向对象的优势(复用、封装),使得实现多线程支持,而接口简单,建议在复杂项目中使用。
· GCD:
任务之间不太依赖 项目中使用GCD的优势是GCD自己很是简单、易用,对于不复杂的多线程操做,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。github
进程百度百科面试
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操做系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。objective-c
线程百度百科数据库
线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程本身不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的所有资源。一个线程能够建立和撤消另外一个线程,同一进程中的多个线程之间能够并发执行。因为线程之间的相互制约,导致线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具有运行的全部条件,逻辑上能够运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每个程序都至少有一个线程,若程序只有一个线程,那就是程序自己。 线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不一样的工做,称为多线程。编程
进程总结c#
- 进程是指在系统中
正在运行
的一个应用程序- 每一个进程之间是
独立
的,每一个进程均运行在其专用且受保护的内存空间内
线程总结
- 1个进程要想执行任务,
必须
得有线程(每1个进程至少要有一个线程
)线程是进程的基本执行单元
,一个进程的全部任务都在线程中执行
进程(process)是一块包含了某些资源的内存区域。操做系统利用进程把它的工做划分为一些功能单元。进程中所包含的一个或多个执行单元称为线程(thread)。进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。一般在一个进程中能够包含若干个线程,它们能够利用进程所拥有的资源。在引入线程的操做系统中,一般都是把进程做为分配资源的基本单位,而把线程做为独立运行和独立调度的基本单位。因为线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提升系统内多个程序间并发执行的程度。简而言之,一个程序至少有一个进程,一个进程至少有一个线程。一个程序就是一个进程,而一个程序中的多个任务则被称为线程。 线程只能归属于一个进程而且它只能访问该进程所拥有的资源。当操做系统建立一个进程后,该进程会自动申请一个名为主线程或首要线程的线程。应用程序(application)是由一个或多个相互协做的进程组成的。另外,进程在执行过程当中拥有独立的内存单元,而多个线程共享内存,从而极大地提升了程序的运行效率。线程在执行过程当中与进程仍是有区别的。每一个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。可是线程不可以独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分能够同时执行。但操做系统并无将多个线程看作多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 进程是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),可是它可与同属一个进程的其余的线程共享进程所拥有的所有资源。
线程与进程对比?
简而言之,一个程序至少有一个进程,一个进程至少有一个线程(即主线程)。一个程序就是一个进程,而一个程序中的多个任务则被称为线程。
学习多线程,先了解手机里有几个重要的芯片:
主芯片:CPU(双核)+GPU(至关于电脑里的显卡)
内存(RAM):至关于电脑的内存条
闪存芯片:相于于电脑的硬盘
电源管理芯片
蓝牙、wifi、gps芯片
多线程应用:
耗时操做(数据库中的读取,图片的处理(滤镜) )
进程是来帮你分配内存的
多线程开线程通常五条之内
全称Grand Central Dispatch,纯C语言,提供了很是多强大的函数
优点:
GCD中2个核心概念:
GCD的使用就两个步骤:
队列的类型: GCD的队列能够分为两种类型:
· 并发队列
(1) 队列中的任务 一般 会并发执行
(2) 可让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
(3) 并发功能只有在异步(dispatch_async)函数下才有效
· 串行队列:
(1) 队列中的任务 只 会顺序执行
(2) 让任务一个接一个的执行(一个任务执行完毕后,再执行下一个任务)
GCD内部是怎么实现的? (1) iOS和OS X的核心是XNU内核,GCD是基于XNU内核实现的
(2) GCD的API所有在libdispatch库中
(3) GCD底层实现主要有Dispatch Queue和Dispatch Source · Dispatch Queue: 管理block(操做) · Dispatch Source :处理事件(MACH端口发送,MACH端口接收,检测与进程相关事件等10种事件)
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t q = dispatch_queue_create("queuename", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t t = dispatch_queue_create("queuename",DISPATCH_QUEUE_SERIAL);
// 实例化一个调度组
dispatch_group_t group = dispatch_group_create();
// 队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 任务添加到队列queue
dispatch_group_async(group, queue, ^{
NSLog(@"下载小说A---%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"下载小说B---%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"下载小说X---%@", [NSThread currentThread]);
});
// 得到全部调度组里面的异步任务完成的通知
// dispatch_group_notify(group, queue, ^{
// NSLog(@"下载完成,请观看%@", [NSThread currentThread]); // 异步的
// });
//注意点: 在调度组完成通知里,能够跨队列通讯
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 更新UI,在主线程
NSLog(@"下载完成,请观看%@", [NSThread currentThread]); // 异步的
});
复制代码
dispatch_group_enter
: 通知 group,下个任务要放入 group 中执行了 dispatch_group_leave
: 通知 group,任务成功完成,要移除,与 enter成对出现 dispatch_group_wait
: 在任务组完成时调用,或者任务组超时是调用(完成指的是enter和leave次数同样多)
dispatch_group_notify
: 只要任务所有完成了,就会在最后调用
- (void)gcdGroupEnterAndLeave {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 请求1
[网络请求:{
成功:dispatch_group_leave(group);
失败:dispatch_group_leave(group);
}];
});
dispatch_group_enter;
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 请求2
[网络请求:{
成功:dispatch_group_leave;
失败:dispatch_group_leave;
}];
});
dispatch_group_enter(group);
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 请求3
[网络请求:{
成功:dispatch_group_leave(group);
失败:dispatch_group_leave(group);
}];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 界面刷新
NSLog(@"任务均完成,刷新界面");
});
}
复制代码
首先是 Apple Documentation 对dispatch_barrier_async的解释
dispatch barrier容许开发者在一个并行队列中创造一个同步点,其实也是用于在竞争条件下资源的保护,防止同一资源同时被使用。 在并行异步任务中: barrier_sync前的任务并发执行,syncbarrier后的任务必须等syncbarrier中的任务执行完成以后才会执行他们,也会阻塞主线程的任务
barrier_async前的任务并发执行,barrier_async后的任务必须等barrier_async中的任务执行完成以后才会执行他们,可是Barrier不能阻塞主线程的任务
做用如:打造线程安全的 NSMutableArray NSMutableArray自己是线程不安全的。简单来讲,线程安全就是多个线程访问同一段代码,程序不会异常、不Crash。而编写线程安全的代码主要依靠线程同步。 一、不使用atomic修饰属性打造线程安全的缘由: 1 ) atomic 的内存管理语义是原子性的,仅保证了属性的setter和getter方法是原子性的,是线程安全的,可是属性的其余方法,如数组添加/移除元素等并非原子操做,因此不能保证属性是线程安全的。 2 ) atomic虽然保证了getter、setter方法线程安全,可是付出的代价很大,执行效率要比nonatomic慢不少倍(有说法是慢10-20倍)。 总之:使用nonatomic修饰NSMutableArray对象就能够了,而使用锁、dispatch_queue来保证NSMutableArray对象的线程安全。 二、打造线程安全的NSMutableArray 在《Effective Objective-C 2.0..》书中第41条:多用派发队列,少用同步锁中指出:使用“串行同步队列”(serial synchronization queue),将读取操做及写入操做都安排在同一个队列里,便可保证数据同步。而经过并发队列,结合GCD的栅栏块(barrier)来不只实现数据同步线程安全,还比串行同步队列方式更高效。
在主队列开启异步任务,不会开启新的线程而是依然在主线程中执行代码块中的代码。为何不会阻塞线程? 主队列开启异步任务,虽然不会开启新的线程,可是他会把异步任务下降优先级,等闲着的时候,就会在主线程上执行异步任务。
在主队列开启同步任务,为何会阻塞线程? 在主队列开启同步任务,由于主队列是串行队列,里面的线程是有顺序的,先执行完一个线程才执行下一个线程,而主队列始终就只有一个主线程,主线程是不会执行完毕的,由于他是无限循环的,除非关闭应用程序。所以在主线程开启一个同步任务,同步任务会想抢占执行的资源,而主线程任务一直在执行某些操做,不愿放手。两个的优先级都很高,最终致使死锁,阻塞线程了。
主线程队列注意: 下面代码执行顺序 1111 2222
- (void)main_queue_deadlock {
dispatch_queue_t q = dispatch_get_main_queue();
NSLog(@"1111");
dispatch_async(q, ^{
NSLog(@"主队列异步 %@", [NSThread currentThread]);
});
NSLog(@"2222");
// 下面会形成线程死锁
// dispatch_sync(q, ^{
// NSLog(@"主队列同步 %@", [NSThread currentThread]);
// });
}
复制代码
dispatch_queue_t q = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_async(q, ^{
NSLog(@"异步任务 %@", [NSThread currentThread]);
// 下面开启同步形成死锁:由于串行队列中线程是有执行顺序的,须要等上面开启的异步任务执行完毕,才会执行下面开启的同步任务。而上面的异步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
dispatch_sync(q, ^{
NSLog(@"同步任务 %@", [NSThread currentThread]);
});
});
复制代码
dispatch_queue_t q = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q, ^{
NSLog(@"同步任务 %@", [NSThread currentThread]);
// 下面开启同步形成死锁:由于串行队列中线程是有执行顺序的,须要等上面开启的同步任务执行完毕,才会执行下面开启的同步任务。而上面的同步任务还没执行完,要到下面的大括号才算执行完毕,而下面的同步任务已经在抢占资源了,就会发生死锁。
dispatch_sync(q, ^{
NSLog(@"同步任务 %@", [NSThread currentThread]);
});
});
NSLog(@"同步任务 %@", [NSThread currentThread]);
复制代码
dispatch_queue_t q = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
// 任务嵌套
dispatch_sync(q, ^{
NSLog(@"1 %@", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"2 %@", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"3 %@", [NSThread currentThread]);
});
});
dispatch_async(q, ^{
NSLog(@"4 %@", [NSThread currentThread]);
});
NSLog(@"5 %@", [NSThread currentThread]);
});
// 运行结果是: 12345 或12354
复制代码
并行队列里开启同步任务是有执行顺序的,只有异步才没有顺序
串行队列开启异步任务,是有顺序的
// 建立队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 建立3个操做
NSOperation *a = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"operationA---");
}];
NSOperation *b = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"operationB---");
}];
NSOperation *c = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"operationC---");
}];
// 添加依赖
[c addDependency:a];
[c addDependency:b];
// 执行操做
[queue addOperation:a];
[queue addOperation:b];
[queue addOperation:c];
复制代码
存放NSOperation的集合类。
(1) 用来存放NSOperation对象的队列,能够用来异步执行一些操做
(2) 通常能够用在网络请求等耗时操做
解释:操做和操做队列,基本能够当作java中的线程和线程池的概念。用于处理ios多线程开发的问题。网上部分资料提到一点是,虽然是queue,可是却并非带有队列的概念,放入的操做并不是是按照严格的先进现出。
这边又有个疑点是,对于队列来讲,先进先出的概念是Afunc添加进队列,Bfunc紧跟着也进入队列,Afunc先执行这个是必然的,可是Bfunc是等Afunc彻底操做完之后,B才开始启动而且执行,所以队列的概念离乱上有点违背了多线程处理这个概念。可是转念一想其实能够参考银行的取票和叫号系统。所以对于A比B先排队取票可是B率先执行完操做,咱们亦然能够感性认为这仍是一个队列。可是后来看到一票关于这操做队列话题的文章,其中有一句提到“由于两个操做提交的时间间隔很近,线程池中的线程,谁先启动是不定的。”瞬间以为这个queue名字有点忽悠人了,还不如pool~综合一点,咱们知道他能够比较大的用处在于能够帮组多线程编程就行了。
// 建立线程的方式1
- (void)createThread1 {
// 建立线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"http://a.png"];
thread.name = @"下载线程";
// 启动线程(调用self的download方法)
[thread start];
}
// 建立线程的方式2
- (void)createThread2 {
[NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"http://b.jpg"];
}
// 建立线程的方式3
- (void)createThread3 {
// 这2个不会建立线程,在当前线程中执行
// [self performSelector:@selector(download:) withObject:@"http://c.gif"];
// [self download:@"http://c.gif"];
[self performSelectorInBackground:@selector(download:) withObject:@"http://c.gif"];
}
复制代码
-(void)threadSafe {
self.leftTicketCount = 50;
self.thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread1.name = @"1号窗口";
self.thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread2.name = @"2号窗口";
self.thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread3.name = @"3号窗口";
[self threadSafeStart];
}
- (void)threadSafeStart {
[self.thread1 start];
[self.thread2 start];
[self.thread3 start];
}
// 卖票
- (void)saleTicket {
while (1) {
// ()小括号里面放的是锁对象
@synchronized(self) { // 开始加锁
int count = self.leftTicketCount;
if (count > 0) {
[NSThread sleepForTimeInterval:0.05];
self.leftTicketCount = count - 1;
NSLog(@"%@卖了一张票, 剩余%d张票", [NSThread currentThread].name, self.leftTicketCount);
} else {
return; // 退出循环
}
} // 解锁
}
}
复制代码
主线程 每个应用程序都只有一个主线程。
全部UI的更新工做,都必须在主线程上执行! 主线程是一直工做的,并且除非将程序杀掉,不然主线程的工做永远不会结束!
队列和线程的区别:
队列是管理线程的,至关于线程池,能管理线程何时执行。
队列分为串行队列和并行队列:
串行队列:队列中的线程按顺序执行(不会同时执行)
并行队列:队列中的线程会并发执行,可能会有一个疑问,队列不是先进先出吗,若是后面的任务执行完了,怎么出去的了。这里须要强调下,任务执行完毕了,不必定出队列。只有前面的任务执行完了,才会出队列,也就是说你即便执行完毕了,也必须等前面的任务执行完毕出队列,才能够出去。
主线程和工做线程的区别:
主线程: 系统自动建立 能直操做UI 不能作耗时比较多的操做 自带自动释放池 RunLoop自动运行
工做线程:程序猿手工建立 不能直接操做UI 写死循环都行 须要手工写自动释放池 手动运行
主线程队列和GCD建立的队列区别: 主线程队列:主线程队列中不能开启同步,会阻塞主线程。只能开启异步任务,开启异步任务也不会开启新的线程,只是下降异步任务的优先级,让cpu空闲的时候才去调用。而同步任务,会抢占主线程的资源,会形成死锁。 GCD建立的队列:在GCD中建立的队列优先级没有主队列高,因此在GCD中的串行队列开启同步任务里面没有嵌套任务是不会阻塞主线程,只有一种可能致使死锁,就是串行队列里,嵌套开启任务,有可能会致使死锁。
同步与异步的区别: 同步任务优先级高,在线程中有执行顺序,不会开启新的线程。 异步任务优先级低,在线程中执行没有顺序,看cpu闲不闲。在主队列中不会开启新的线程,其余队列会开启新的线程。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 下载图片
UIImage *image = nil;
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程
});
// [self performSelector:@selector(settingImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES modes:nil];
// [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:YES];
});
复制代码
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
函数内部是经过NSTimer定时器实现,在NSRunLoop没有开启的状况下,NSTimer不会获得正常运行。dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self performSelector:@selector(fireBlock:) withObject:^{
NSLog(@"hello world");
} afterDelay:0.3];
});
复制代码
[self performSelectorOnMainThread: withObject: waitUntilDone:];
[self performSelector: onThread:[NSThread mainThread] withObject: waitUntilDone:];
dispatch_async(dispatch_get_main_queue(), ^{
});
复制代码
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
});
[self performSelector: withObject: afterDelay:];
[NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:];
复制代码
GCD怎么用的? 全局队列异步操做,会新建多个子线程,操做无序执行,若是队列前有其余任务,会等待其余任务执行完毕在调用; 全局队列同步操做,不会新建线程,顺序执行; 主队列全部的操做都是主线程顺序执行,没有异步概念,主队列添加的同步操做永远不会执行,会死锁; 串行队列添加的同步操做会死锁,可是会执行嵌套同步操做以前的代码; 并行队列添加的同步操做不会死锁都在主线程执行; 全局队列添加的同步操做不会死锁; 同步操做 最主要的目的,阻塞并行队列任务的执行,只有当前的同步任务执行完毕以后,后边的任务才会执行,应用:用户登陆。
多线程安全怎么控制:
@synchronized @synchronized 的做用是建立一个互斥锁,保证此时没有其它线程对self对象进行修改。这个是objective-c的一个锁定令牌,防止self对象在同一时间内被其它线程访问,起到线程的保护做用。 通常在公用变量的时候使用,如单例模式或者操做类的static变量中使用。
NSLock 从微观上看一个线程在CPU上走走停停的,其运行状态能够分为(经典)三种:运行状态、就绪状态、阻塞。 两个线程同时访问一个共享的变量,一个对其加一、一个对其减1 因为内存的速度远低于CPU的速度,因此在设计CPU时一般不容许直接对内存中的数据进行运行。若是要运算内存中的数据一般是用一条CPU指令把内存中的数据读入CPU、再用另一CPU指令对CPU中的数据作运算、最后再用一条CPU指令把结果写回内存。 i++ 读数据 运算 写数据 因为CPU在执行两条指令中间能够被打断,就可能致使另外一个访问一样内存的线程运行,最终致使运算结果出错 解决办法就是加线程锁 NSLock lock方法 加锁:若是这个没被锁上则直接上锁、若是锁已经被其它线程锁上了当前线程就阻塞直至这个锁被其它线程解锁 unlock方法 解锁:解开这个锁,若是有其它线程由于等这个锁而进入了阻塞状态还要把那个线程变成就绪 用lock保护共享数据的原理 先上锁 访问共享的数据(临界区) 解锁
NSCondition 线程的同步,有一个经典的生产者消费者问题: 好比一个线程A负责下载数据 另外一个线程B负责处理数据 还有一个线程C负责显示 解决方法就是用NSCondition: lock wait signal unlock 产生者线程(产生数据的线程),生产数据以后: lock signal(发出信号:若是有其它线程在等待这个信号就把那个线程变为就绪状态) unlock 消费者线程(处理或使用数据的线程): lock wait(等待信号:若是有线程发信号当前线程就会进入阻塞状态、直到有线程发出信号) unlock NSCondition有一个问题:假唤醒(wait的时候明明没有线程发信号,wait也可能返回),一般用一个表示状态的变量就能解决这个问题
不可改变的对象,一般是线程安全的 线程安全的类和函数: NSArray, NSData, NSNumber..... 非线程安全: NSBundle, NSCoder, NSArchiver, NSMutableArray
列举几种进程的同步机制,并比较其优缺点。 答案:原子操做、信号量机制、自旋锁、管程、会合、分布式系统
进程之间通讯的途径 答案:共享存储系统消息传递系统管道:以文件系统为基础
进程死锁的缘由 答案:资源竞争及进程推动顺序非法
死锁的4个必要条件 答案:互斥、请求保持、不可剥夺、环路
死锁的处理 答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁