iOS开发中关于多线程的问题(NSOperationQueue,NSThread,GCD)

iOS多线程技术与实践 合理的管理和分配任务到主线程与工作线程是提升iOS应用性能的关键。通过本章节的介绍,我们了解了工作线程与主线程之间的职责差异,以及如何通过使用NSOperation和NSBlockOperation来管理和执行后台任务,同时介绍了线程间通信和数据同步的重要性。通过掌握这些知识,开发者可以更好地控制多线程的执行和避免常见的并发问题。尽管NSThread提供了更多的控制自由度,但也带来了复杂性和潜在的错误。对于大多数iOS多线程任务,GCD和NSOperationQueue提供的抽象层更为推荐。 阅读详情
1.多线程的优点和缺点分别是什么?
答:优点:1、将耗时较长的操作(网络请求、图片下载、音频下载、数据库访问等)放在子线程中执行,可以防止主线程的卡死;2、可以发挥多核处理的优势,提升cpu的使用率。
      缺点:1、每开辟一个子线程就消耗一定的资源; 2、会造成代码的可读性变差;3、如果出现多个线程同时访问一个资源,会出现资源争夺的情况
3. 2.NSOperationQueue中有一个属性叫maxConcurrentCount即最大并发数。这里所谓的最大并发数指的是什么含义?
答:这里的最大并发数指得是在队列中同时执行的任务的个数。有很多人会认为是所分配的线程的个数。其实不是的。因为线程的个数的多少取决于系统,系统会分配合适的线程数量来保证这些任务并发执行的,作为程序员我们是没办法控制的
4、NSThread中的Runloop的作用,如何使用?
每个线程(NSThread)对象中内部都有一个run loop(NSRunLoop)对象用来循环处理输入事件,处理的事件包括两类,一是来自Input sources的异步事件,一是来自Timer sources的同步事件;run Loop在处理输入事件时会产生通知,可以通过Core Foundation向线程中添加run-loop observers来监听特定事件,以在监听的事件发生时做附加的处理工作。 主线程的Run Loop会在App运行时自动运行,子线程中需要手动运行。Run Loop就是一个处理事件源的循环,你可以控制这个Run Loop运行多久,如果当前没有事件发生,Run Loop会让这个线程进入睡眠状态(避免再浪费CPU时间),如果有事件发生,Run Loop就处理这个事件。如果子线程进入一个循环需要不断处理一些事件,那么设置一个Run Loop是最好的处理方式,如果需要Timer,那么Run Loop就是必须的。
 
开发中遇到的需要使用Run Loop的情况有:
需要使用Port或者自定义Input Source与其他线程进行通讯。
子线程中使用了定时器
使用任何perform mSelector*****到子线程中运行方法
使用子线程去执行周期性任务
NSURLConnection在子线程中发起异步请求
 
 10)OC中创建线程的方法是什么?如果在主线程中执行代码,方法是什么
线程创建有三种方法:使用NSThread创建、使用 GCD的dispatch、使用子类化的 NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:
 
11)线程和进程的区别和联系
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。 
 
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
 
 
9.在项目什么时候选择使用GCD,什么时候选择NSOperation? 
 
gcd是基于c的底层api,NSOperation属于object-c类。
相对于gcd:
1,NSOperation拥有更多的函数可用,具体查看api。
2,在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。
3,有kvo,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)。
4,NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
gcd主要与block结合使用。
 
项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
 
1、线程的堆栈大小
 
iPhone设备上的应用程序开发也是属于嵌入式设备的开发,同样需要注意嵌入式设备开发时的几点问题,比如资源上限,处理器速度等。
iPhone 中的线程应用并不是无节制的,官方给出的资料显示iPhone OS下的主线程的堆栈大小是1M,第二个线程开始都是512KB。并且该值不能通过编译器开关或线程API函数来更改。
 
2、Autorelease
如果你什么都不考虑,在线程函数内调用 autorelease,会出现错误
 
3、子线程中描画窗口
多线程编程中普遍遵循一个原则,就是一切与UI相关的操作都有主线程做,子线程只负责事务,数据方面的处理。那么如果想在子线程中更新UI时怎么做呢?如果是在windows下,你会 PostMessage 一个描画更新的消息,在iPhone中,需要使用performSelectorOnMainThread 委托主线程处理。
 
总结:
多线程能适当提高程序的执行效率,能适当提高资源利用率(CPU、内存利用率),但是开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能,而且线程越多,CPU在调度线程上的开销就越大,使用多线程程序设计更加复杂:比如线程之间的通信、多线程的数据共享
 
一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的使用注意:别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
25. 线程是什么?进程是什么?二者有什么区别和联系? (UI第二十二讲 多线程编程)
线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。
 
26.谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?(UI第二十二讲 多线程编程)
好处:
①、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载
②、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好
缺点:
①、大量的线程降低代码的可读性,
②、更多的线程需要更多的内存空间
③、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:
①、NSThread(两种创建方式)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
②、NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//这个block语句块在子线程中执行
}

③、Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 耗时的操作
    dispatch_async(dispatch_get_main_queue(), ^{
        // 更新界面
    });
});

PS:不显示的创建线程的方法:
用NSObject的类方法 performSelectorInBackground:withObject:
创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
 
 
27.线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
异步:同时去做两件或者多件事。比如边听歌边看报。
.runloop和线程有什么关系?
总的说来,Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa 和 CoreFundation 都提供了 run loop 对象方便配置和管理线程的 run loop (以下都以 Cocoa 为例)。每个线程,包括程序的主线程( main thread )都有与之相应的 run loop 对象。
runloop 和线程的关系:主线程的run loop默认是启动的。iOS的应用程序里面,程序启动后会有一个如下的main()函数
int main(int argc, char * argv[]) {
@autoreleasepool {
         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
51. GCD的队列(dispatch_queue_t)分哪两种类型?
串行队列Serial Dispatch Queue
并行队列Concurrent Dispatch Queue
77. 你参与的APP,是如何处理多个服务的同步发起的?
使用iOS线程技术,创建并行队列来分别执行不同的任务。将不同的任务加入到子队列当中,任务执行后回到主线程当中刷新UI界面。
APP 界面一般都是根据产品需求和UI效果图来完成的,但是我们为了提高代码的复用性,会将视图的实现进行封装,然后在控制器当中进行加载用
88.NSOperationQueue有哪些使用方式?
一种在iOS中执行并发操作的方法,是使用NSOperation和NSOperationQueue类。在本教程中,你将学习如何使用它们!你会先创建一款不使用多线程的app,这样它会变得响应非常迟钝。然后改进程序,添加上并行操作–并且希望–可以提供一个交互响应更好的界面给用户!
另一种处理操作之间的依赖关系,如果操作直接有依赖关系,比如第二个操作必须等第一个操作结束后再执行。控制线程池中的线程数
89.NSThread中的Runloop的作用,如何使用?
有些情况下,我们还是在运行一些长线任务或者复杂任务的时候需要用比较原始的NSThread。这就需要为NSThread创建一个run loop.
          1 NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(playerThread: ) object:nil];  
         2       [thread start];  
         3       //如果要利用NSOperation,原理类似。只需要加入到queue里面去就好了。。queue会在合适的时机调用方法,下面代码作为参考。  
         4       - (void) playerThread: (void*)unused   
         5       {   
         6       audioRunLoop = CFRunLoopGetCurrent();//子线程的runloop引用 
         7       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//子线程的  
         8       [self initPlayer]; CFRunLoopRun(); //运行子线程的  
         9       [pool release];  // run loop,这里就会停住了。
         10     }  
         11      // 实现一个timer,用于检查子线程的工作状态,并在合适的时候做任务切换。或者是合适的时候停掉自己的
 
         12      -(void) initPlayer {   
         13      // 在这里你可以初始化一个工作类,比如声音或者视频播放   
         14      NSTimer *stateChange = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:  
         15        @selector(checkStatuserInfo:nil repeats:YES];  
         16      }  
         17      -(void) checkState:(NSTimer*) timer   
         18      {   
         19      if(需要退出自线程了) {  
         20      //释放子线程里面的资源  
         21      CFRunLoopStop( CFRunLoopGetCurrent());//结束子线程任务  
         22      }   
         23     } 
3. NSThread、NSOperationQueue以及GCD等多线程编程技术什么情况下使用?
 
1)NSThread
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
 

2)Cocoa  NSOperation
优点:不需要关心线程管理, 数据同步的事情,可以把精力放在自己需要执行的操作上。
Cocoa operation相关的类是NSOperation, NSOperationQueue.
NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类: NSInvocationOperation和NSBlockOperation.
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。
2)GCD使用过程中遇到的问题?
 
44.项目中哪块用到多线程,碰到了什么问题,怎么解决的
 
什么时候使用多线程:
将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐,文件下载等。
 
碰到的问题以及解决办法:
(1)使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢
使用以下方法可以控制并发的线程数量:
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序
(2)当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
(3)更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理。
‘多线程中栈与堆是公有的还是私有的
一般来说栈是私有的,堆是公有的;但是可以为特定的线程创建私有的堆
 
在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。
 
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
 
24、描述runloop和线程的关系
Run loop,正如其名,loop表⽰示某种循环,和run放在⼀一起就表⽰示⼀一直在运⾏行着 的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线 程⽽而⽣生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa和CoreFundation都提供了run loop对象⽅方便配置和管理线程的run loop(以
下都已Cocoa为例)。每个线程,包括程序的主线程(main thread)都有与之相 应的run loop对象。
 
8、GCD的队列(dispatch_queue_t)分哪两种类型?编写代码:使⽤用并⾏行队列 实现多线程开发
串⾏行队列Serial Dispatch Queue
并⾏行队列Concurrent Dispatch Queue
1
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO RITY_DEFAULT, 0);
2
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO
RITY_HIGH, 0);
3
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO RITY_LOW, 0);

1、列举Cocoa中常见对几种线程的实现,并谈谈多线程安全的几种解决办法和多线程安全怎么控制.
 
Cocoa中常见对几种线程的实现:
(1)OC的NSThread
(2) C语言的GCD接口(性能最好,代码更精简) 
(3) OC的NSOperation和NSOperationQueue(基于GCD)
 
多线程安全的几种解决办法
 (1)只在主线程刷新访问UI
 (2)如果要防止资源抢夺,得用synchronize进行加锁保护。
 (3)如果异步操作要保证线程安全等问题,尽量使用GCD。(GCD有些函数默认就是安全的)


19.多线程在实际项目中的应用中有没有碰到什么问题什么时候使用多线程:
将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐,文件下载等。
 
       碰到的问题以及解决办法:
       (1)使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢
       使用以下方法可以控制并发的线程数量:
       -(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
       使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序
       (2)当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
       (3)更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理
3. 2.NSOperationQueue中有一个属性叫maxConcurrentCount即最大并发数。这里所谓的最大并发数指的是什么含义?
答:这里的最大并发数指得是在队列中同时执行的任务的个数。有很多人会认为是所分配的线程的个数。其实不是的。因为线程的个数的多少取决于系统,系统会分配合适的线程数量来保证这些任务并发执行的,作为程序员我们是没办法控制的
4.在项目中什么时候选择使用GCD,什么时候选择使用NSOperation?
答:无论是GCD还是NSOperation其实都是多线程的一种实现形式。严格的说NSOperation和线程并没有必然联系,更不是多线程,NSOperation只是操作,封装了target和action 或者Block,在主线程中执行Operation,Operation就会运行在主线程中,在子线程中执行Operation,Operation就运行在子线程中。它只有和NSOperationQueue联合使用的时候,才能发挥出价值。NSOperationQueue是Operation的管理者,它首先是一个队列,先来的任务先开始执行,后来的任务后开始执行,这些任务的执行是并发的,NSOperationQueue负责为任务开辟线程以及关闭线程,有点类似于cell重用,用有限的线程执行任意数量的任务,同时可以设置最大并发数,控制程序的性能,不至于全部任务一起执行。GCD出现比NSOperationQueue要晚,是一套基于C函数的API,由于是C函数,所以性能比较高,使用灵活,安全,当然功能也强大。但是相对于GCD来讲,NSOperationQueue对线程做了封装,使用比较简单,尤其是不用管理线程的开启和关闭。个人认为,如果仅仅是想要实现异步执行任务,首选GCD,如果要管理多个异步任务,NSoperationQueue比较方便。如果要做更复杂的处理,比如前5个任务并发,5个任务执行完之后,需要串行执行3个任务,之后再并发执行若干任务,就需要使用GCD了。总的来说,特别简单的和非常复杂的多线程任务GCD比较适合,介于二者之间的用NSOperationQueue比较合适。
5.写出在多线程情况下的一个单例。
答:一般情况下,在开发中我们所写的单例都是伪单例。即只是保证了在调用某一方法时,所产生的对象只有一个,但是没有考虑其他的影响其引用计数的方法。例如retain、copy等。为了保证线程安全,单例的写法如下所示:
方法一:
static AccountManager *sharedAccountManagerInstance = nil; 
+ (AccountManager *)sharedManager{ 
         @synchronized (self){
                   if (sharedAccountManagerInstance == nil) {
                            sharedAccountManagerInstance = [[AccountManager alloc] init];
                   }
         }
         return sharedAccountManagerInstance; 
}
方法二:
static AccountManager *sharedAccountManagerInstance = nil; 
+ (AccountManager *)sharedManager 
{ 
         static dispatch_once_t onceToken; 
         dispatch_once(&onceToken, ^{ 
                   sharedAccountManagerInstance = [[AccountManager alloc] init];  
         }); 
         return sharedAccountManagerInstance; 
}

 10)OC中创建线程的方法是什么?如果在主线程中执行代码,方法是什么
线程创建有三种方法:使用NSThread创建、使用 GCD的dispatch、使用子类化的 NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:
 
11)线程和进程的区别和联系
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
 
2、Autorelease
如果你什么都不考虑,在线程函数内调用 autorelease,会出现错误
 
3、子线程中描画窗口
多线程编程中普遍遵循一个原则,就是一切与UI相关的操作都有主线程做,子线程只负责事务,数据方面的处理。那么如果想在子线程中更新UI时怎么做呢?如果是在windows下,你会 PostMessage 一个描画更新的消息,在iPhone中,需要使用performSelectorOnMainThread 委托主线程处理。
 
总结:
多线程能适当提高程序的执行效率,能适当提高资源利用率(CPU、内存利用率),但是开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能,而且线程越多,CPU在调度线程上的开销就越大,使用多线程程序设计更加复杂:比如线程之间的通信、多线程的数据共享
 
一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的使用注意:别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
25. 线程是什么?进程是什么?二者有什么区别和联系? (UI第二十二讲 多线程编程)
线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。
 
26.谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?(UI第二十二讲 多线程编程)
好处:
①、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载
②、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好
缺点:
①、大量的线程降低代码的可读性,
②、更多的线程需要更多的内存空间
③、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:
①、NSThread(两种创建方式)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
②、NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//这个block语句块在子线程中执行
}

③、Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 耗时的操作
    dispatch_async(dispatch_get_main_queue(), ^{
        // 更新界面
    });
});

PS:不显示的创建线程的方法:
用NSObject的类方法 performSelectorInBackground:withObject:
创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
 
 
27.线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
异步:同时去做两件或者多件事。比如边听歌边看报。
.runloop和线程有什么关系?
总的说来,Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa 和 CoreFundation 都提供了 run loop 对象方便配置和管理线程的 run loop (以下都以 Cocoa 为例)。每个线程,包括程序的主线程( main thread )都有与之相应的 run loop 对象。
runloop 和线程的关系:主线程的run loop默认是启动的。iOS的应用程序里面,程序启动后会有一个如下的main()函数
int main(int argc, char * argv[]) {
@autoreleasepool {
         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
51. GCD的队列(dispatch_queue_t)分哪两种类型?
串行队列Serial Dispatch Queue
并行队列Concurrent Dispatch Queue
77. 你参与的APP,是如何处理多个服务的同步发起的?
使用iOS线程技术,创建并行队列来分别执行不同的任务。将不同的任务加入到子队列当中,任务执行后回到主线程当中刷新UI界面。
APP 界面一般都是根据产品需求和UI效果图来完成的,但是我们为了提高代码的复用性,会将视图的实现进行封装,然后在控制器当中进行加载调用
88.NSOperationQueue有哪些使用方式?
一种在iOS中执行并发操作的方法,是使用NSOperation和NSOperationQueue类。在本教程中,你将学习如何使用它们!你会先创建一款不使用多线程的app,这样它会变得响应非常迟钝。然后改进程序,添加上并行操作–并且希望–可以提供一个交互响应更好的界面给用户!
另一种处理操作之间的依赖关系,如果操作直接有依赖关系,比如第二个操作必须等第一个操作结束后再执行。控制线程池中的线程数

3. NSThread、NSOperationQueue以及GCD等多线程编程技术什么情况下使用?
 
1)NSThread
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
 
 
2)Cocoa  NSOperation
优点:不需要关心线程管理, 数据同步的事情,可以把精力放在自己需要执行的操作上。
Cocoa operation相关的类是NSOperation, NSOperationQueue.
NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类: NSInvocationOperation和NSBlockOperation.
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

 
44.项目中哪块用到多线程,碰到了什么问题,怎么解决的
 
什么时候使用多线程:
将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐,文件下载等。
 
碰到的问题以及解决办法:
(1)使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢
使用以下方法可以控制并发的线程数量:
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序
(2)当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
(3)更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理。
‘多线程中栈与堆是公有的还是私有的
一般来说栈是私有的,堆是公有的;但是可以为特定的线程创建私有的堆
 
在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。
 
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。

1、列举Cocoa中常见对几种线程的实现,并谈谈多线程安全的几种解决办法和多线程安全怎么控制.
 
Cocoa中常见对几种线程的实现:
(1)OC的NSThread
(2) C语言的GCD接口(性能最好,代码更精简) 
(3) OC的NSOperation和NSOperationQueue(基于GCD)
 
多线程安全的几种解决办法
 (1)只在主线程刷新访问UI
 (2)如果要防止资源抢夺,得用synchronize进行加锁保护。
 (3)如果异步操作要保证线程安全等问题,尽量使用GCD。(GCD有些函数默认就是安全的)

3. 2.NSOperationQueue中有一个属性叫maxConcurrentCount即最大并发数。这里所谓的最大并发数指的是什么含义?
答:这里的最大并发数指得是在队列中同时执行的任务的个数。有很多人会认为是所分配的线程的个数。其实不是的。因为线程的个数的多少取决于系统,系统会分配合适的线程数量来保证这些任务并发执行的,作为程序员我们是没办法控制的
4.在项目中什么时候选择使用GCD,什么时候选择使用NSOperation?
答:无论是GCD还是NSOperation其实都是多线程的一种实现形式。严格的说NSOperation和线程并没有必然联系,更不是多线程,NSOperation只是操作,封装了target和action 或者Block,在主线程中执行Operation,Operation就会运行在主线程中,在子线程中执行Operation,Operation就运行在子线程中。它只有和NSOperationQueue联合使用的时候,才能发挥出价值。NSOperationQueue是Operation的管理者,它首先是一个队列,先来的任务先开始执行,后来的任务后开始执行,这些任务的执行是并发的,NSOperationQueue负责为任务开辟线程以及关闭线程,有点类似于cell重用,用有限的线程执行任意数量的任务,同时可以设置最大并发数,控制程序的性能,不至于全部任务一起执行。GCD出现比NSOperationQueue要晚,是一套基于C函数的API,由于是C函数,所以性能比较高,使用灵活,安全,当然功能也强大。但是相对于GCD来讲,NSOperationQueue对线程做了封装,使用比较简单,尤其是不用管理线程的开启和关闭。个人认为,如果仅仅是想要实现异步执行任务,首选GCD,如果要管理多个异步任务,NSoperationQueue比较方便。如果要做更复杂的处理,比如前5个任务并发,5个任务执行完之后,需要串行执行3个任务,之后再并发执行若干任务,就需要使用GCD了。总的来说,特别简单的和非常复杂的多线程任务GCD比较适合,介于二者之间的用NSOperationQueue比较合适。
5.写出在多线程情况下的一个单例。
答:一般情况下,在开发中我们所写的单例都是伪单例。即只是保证了在调用某一方法时,所产生的对象只有一个,但是没有考虑其他的影响其引用计数的方法。例如retain、copy等。为了保证线程安全,单例的写法如下所示:
方法一:
static AccountManager *sharedAccountManagerInstance = nil; 
+ (AccountManager *)sharedManager{ 
         @synchronized (self){
                   if (sharedAccountManagerInstance == nil) {
                            sharedAccountManagerInstance = [[AccountManager alloc] init];
                   }
         }
         return sharedAccountManagerInstance; 
}
方法二:
static AccountManager *sharedAccountManagerInstance = nil; 
+ (AccountManager *)sharedManager 
{ 
         static dispatch_once_t onceToken; 
         dispatch_once(&onceToken, ^{ 
                   sharedAccountManagerInstance = [[AccountManager alloc] init];  
         }); 
         return sharedAccountManagerInstance; 
}
4、NSThread中的Runloop的作用,如何使用?
每个线程(NSThread)对象中内部都有一个run loop(NSRunLoop)对象用来循环处理输入事件,处理的事件包括两类,一是来自Input sources的异步事件,一是来自Timer sources的同步事件;
run Loop在处理输入事件时会产生通知,可以通过Core Foundation向线程中添加run-loop observers来监听特定事件,以在监听的事件发生时做附加的处理工作。 主线程的Run Loop会在App运行时自动运行,子线程中需要手动运行。


 
Run Loop就是一个处理事件源的循环,你可以控制这个Run Loop运行多久,如果当前没有事件发生,Run Loop会让这个线程进入睡眠状态(避免再浪费CPU时间),如果有事件发生,Run Loop就处理这个事件。
如果子线程进入一个循环需要不断处理一些事件,那么设置一个Run Loop是最好的处理方式,如果需要Timer,那么Run Loop就是必须的。
 
开发中遇到的需要使用Run Loop的情况有:
需要使用Port或者自定义Input Source与其他线程进行通讯。
子线程中使用了定时器
使用任何perform mSelector*****到子线程中运行方法
使用子线程去执行周期性任务
NSURLConnection在子线程中发起异步请求
 
 10)OC中创建线程的方法是什么?如果在主线程中执行代码,方法是什么
线程创建有三种方法:使用NSThread创建、使用 GCD的dispatch、使用子类化的 NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:
 
11)线程和进程的区别和联系
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。 
 
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程
 
 
9.在项目什么时候选择使用GCD,什么时候选择NSOperation? 
 
gcd是基于c的底层api,NSOperation属于object-c类。
相对于gcd:
1,NSOperation拥有更多的函数可用,具体查看api。
2,在NSOperationQueue中,可以建立各个NSOperation之间的依赖关系。
3,有kvo,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)。
4,NSOperationQueue可以方便的管理并发、NSOperation之间的优先级。
gcd主要与block结合使用。
 
项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。

 
1、线程的堆栈大小
 
iPhone设备上的应用程序开发也是属于嵌入式设备的开发,同样需要注意嵌入式设备开发时的几点问题,比如资源上限,处理器速度等。
iPhone 中的线程应用并不是无节制的,官方给出的资料显示iPhone OS下的主线程的堆栈大小是1M,第二个线程开始都是512KB。并且该值不能通过编译器开关或线程API函数来更改。
 
2、Autorelease
如果你什么都不考虑,在线程函数内调用 autorelease,会出现错误
 
3、子线程中描画窗口
多线程编程中普遍遵循一个原则,就是一切与UI相关的操作都有主线程做,子线程只负责事务,数据方面的处理。那么如果想在子线程中更新UI时怎么做呢?如果是在windows下,你会 PostMessage 一个描画更新的消息,在iPhone中,需要使用performSelectorOnMainThread 委托主线程处理。
 
总结:
多线程能适当提高程序的执行效率,能适当提高资源利用率(CPU、内存利用率),但是开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能,而且线程越多,CPU在调度线程上的开销就越大,使用多线程程序设计更加复杂:比如线程之间的通信、多线程的数据共享
 
一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的使用注意:别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
25. 线程是什么?进程是什么?二者有什么区别和联系? (UI第二十二讲 多线程编程)
线程是CPU独立运行和独立调度的基本单位(可以理解为一个进程中执行的代码片段),进程是资源分配的基本单位(进程是一块包含了某些资源的内存区域)。进程是线程的容器,真正完成代码执行的是线程,而进程则作为线程的执行环境。一个程序至少包含一个进程,一个进程至少包含一个线程,一个进程中的多个线程共享当前进程所拥有的资源。
 
26.谈谈你对多线程开发的理解?ios中有几种实现多线程的方法?(UI第二十二讲 多线程编程)
好处:
①、使用线程可以把程序中占据时间长的任务放到后台去处理,如图片、视频的下载
②、发挥多核处理器的优势,并发执行让系统运行的更快、更流畅,用户体验更好
缺点:
①、大量的线程降低代码的可读性,
②、更多的线程需要更多的内存空间
③、当多个线程对同一个资源出现争夺的时候要注意线程安全的问题。
iOS有三种多线程编程的技术:
①、NSThread(两种创建方式)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
[myThread start];
②、NSOperationQueue
NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];
oprationQueue addOperationWithBlock:^{
//这个block语句块在子线程中执行

③、Grand Central Dispatch (GCD)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 耗时的操作
    dispatch_async(dispatch_get_main_queue(), ^{
        // 更新界面
    });
});

PS:不显示的创建线程的方法:
用NSObject的类方法 performSelectorInBackground:withObject:
创建一个线程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
 
 
27.线程同步和异步的区别?IOS中如何实现多线程的同步?
同步:一个线程要等待上一个线程执行完之后才能执行当前的线程,生活中的例子(上厕所)。
异步:同时去做两件或者多件事。比如边听歌边看报。
.runloop和线程有什么关系?
总的说来,Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa 和 CoreFundation 都提供了 run loop 对象方便配置和管理线程的 run loop (以下都以 Cocoa 为例)。每个线程,包括程序的主线程( main thread )都有与之相应的 run loop 对象。
runloop 和线程的关系:主线程的run loop默认是启动的。iOS的应用程序里面,程序启动后会有一个如下的main()函数
int main(int argc, char * argv[]) {
@autoreleasepool {
         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
在任何一个 Cocoa 程序的线程中,都可以通过以下代码来获取到当前线程的 run loop 。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
51. GCD的队列(dispatch_queue_t)分哪两种类型?
串行队列Serial Dispatch Queue
并行队列Concurrent Dispatch Queue
77. 你参与的APP,是如何处理多个服务的同步发起的?
使用iOS线程技术,创建并行队列来分别执行不同的任务。将不同的任务加入到子队列当中,任务执行后回到主线程当中刷新UI界面。
APP 界面一般都是根据产品需求和UI效果图来完成的,但是我们为了提高代码的复用性,会将视图的实现进行封装,然后在控制器当中进行加载调用
88.NSOperationQueue有哪些使用方式?
一种在iOS中执行并发操作的方法,是使用NSOperation和NSOperationQueue类。在本教程中,你将学习如何使用它们!你会先创建一款不使用多线程的app,这样它会变得响应非常迟钝。然后改进程序,添加上并行操作–并且希望–可以提供一个交互响应更好的界面给用户!
另一种处理操作之间的依赖关系,如果操作直接有依赖关系,比如第二个操作必须等第一个操作结束后再执行。控制线程池中的线程数
89.NSThread中的Runloop的作用,如何使用?
有些情况下,我们还是在运行一些长线任务或者复杂任务的时候需要用比较原始的NSThread。这就需要为NSThread创建一个run loop.
         1       NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(playerThread: ) object:nil];  
         2       [thread start];  
         3       //如果要利用NSOperation,原理类似。只需要加入到queue里面去就好了。。queue会在合适的时机调用方法,下面代码作为参考。 
         4       - (void) playerThread: (void*)unused   
         5       {   
         6       audioRunLoop = CFRunLoopGetCurrent();//子线程的runloop引用 
         7       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//子线程的  
         8       [self initPlayer]; CFRunLoopRun(); //运行子线程的  
         9       [pool release];  // run loop,这里就会停住了。
         10     }  
         11      // 实现一个timer,用于检查子线程的工作状态,并在合适的时候做任务切换。或者是合适的时候停掉自己的
 
         12      -(void) initPlayer {   
         13      // 在这里你可以初始化一个工作类,比如声音或者视频播放   
         14      NSTimer *stateChange = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:  
         15        @selector(checkStatuserInfo:nil repeats:YES];  
         16      }  
         17      -(void) checkState:(NSTimer*) timer   
         18      {   
         19      if(需要退出自线程了) {  
         20      //释放子线程里面的资源  
         21      CFRunLoopStop( CFRunLoopGetCurrent());//结束子线程任务  
         22      }   
         23      } 
3. NSThread、NSOperationQueue以及GCD等多线程编程技术什么情况下使用?
 
1)NSThread
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
 

2)Cocoa  NSOperation
优点:不需要关心线程管理, 数据同步的事情,可以把精力放在自己需要执行的操作上。
Cocoa operation相关的类是NSOperation, NSOperationQueue.
NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类: NSInvocationOperation和NSBlockOperation.
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。
2)GCD使用过程中遇到的问题?
 
44.项目中哪块用到多线程,碰到了什么问题,怎么解决的
 
什么时候使用多线程:
将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐,文件下载等。
 
碰到的问题以及解决办法:
(1)使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢
使用以下方法可以控制并发的线程数量:
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序
(2)当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
(3)更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理。
‘多线程中栈与堆是公有的还是私有的
一般来说栈是私有的,堆是公有的;但是可以为特定的线程创建私有的堆
 
在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。
 
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
 
24、描述runloop和线程的关系
Run loop,正如其名,loop表⽰示某种循环,和run放在⼀一起就表⽰示⼀一直在运⾏行着 的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线 程⽽而⽣生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa和CoreFundation都提供了run loop对象⽅方便配置和管理线程的run loop(以
下都已Cocoa为例)。每个线程,包括程序的主线程(main thread)都有与之相 应的run loop对象。
 
8、GCD的队列(dispatch_queue_t)分哪两种类型?编写代码:使⽤用并⾏行队列 实现多线程开发
串⾏行队列Serial Dispatch Queue
并⾏行队列Concurrent Dispatch Queue
1
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO RITY_DEFAULT, 0);
2
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO
RITY_HIGH, 0);
3
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIO RITY_LOW, 0);
  
5、列举几种进程的同步机制并进行比较。
 
(1)信号量机制    一个信号量只能置一次初值,以后只能对之进行p操作或v操作。由此也可以看到,信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点。信号量机制功能强大,但使用时对信号量的操作分散, 而且难以控制,读写和维护都很困难。加重了程序员的编码负担;核心操作P-V分散在各用户程序的代码中,不易控制和管理;一旦错误,后果严重,且不易发现和纠正。
(2)自旋锁  旋锁是为了保护共享资源提出的一种锁机制。调用者申请的资源如果被占用,即自旋锁被已经被别的执行单元保持,则调用者一直循环在那里看是否该自旋锁的保持着已经释放了锁。自旋锁是一种比较低级的保护数据结构和代码片段的原始方式,可能会引起以下两个问题; 1、死锁 2、过多地占用CPU资源 传统自旋锁由于无序竞争会导致“公平性”问题  
(3)管程  信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。
(4)会合 进程直接进行相互作用
(5)分布式系统 由于在分布式操作系统中没有公共内存,因此参数全为值参,而且不可为指针。
 
 
6、导致进程死锁的原因是什么,如何解决。
产生死锁的原因:一是系统提供的资源数量有限,不能满足每个进程的使用;二是多道程序运行时,进程推进顺序不合理。
产生死锁的必要条件是:1、互斥条件;2、不可剥夺条件(不可抢占);
3、部分分配;4、循环等待。
根据产生死锁的四个必要条件,只要使其中之一不能成立,死锁就不会出现。为此,可以采取下列三种预防措施:
1、采用资源静态分配策略,破坏"部分分配"条件;
2、允许进程剥夺使用其他进程占有的资源,从而破坏"不可剥夺"条件;
3、采用资源有序分配法,破坏"环路"条件。
死锁的避免不严格地限制死锁的必要条件的存在,而是系统在系统运行过程中小心地避免死锁的最终发生。最著名的死锁避免算法是银行家算法。死锁避免算法需要很大的系统开销。
解决死锁的另一条途径是死锁检测方法,这种方法对资源的分配不加限制,即允许死锁的发生。但系统定时地运行一个"死锁检测"程序,判断系统是否已发生死锁,若检测到死锁发生则设法加以解除。
 
解除死锁常常采用下面两种方法:1、资源剥夺法;2、撤消进程法
解决策略:鸵鸟策略、预防策略、避免策略、检测与解除死锁
多线程GCD,NSThread,NSOperationQueue,详细解释Demo 该demo详细解释了gcd NSThread NSOperationQueue的用法.详细解释了子线程中如何刷新UI 立即下载

相关推荐

OpenCvSharp之利用海康相机采集图像并在pictureBox中显示

OpenCvSharp之利用海康相机采集图像并在pictureBox中显示 说明:OpenCvSharp版本为4.0 海康相机为黑白相机 实现功能:将海康相机采集的图像转成Mat,并在pictureBox中显示。 示例代码: Mat srcImage; private Mat CaptureImage() { int nRet; //MyCamera.MVCC_I...

Kevin_Sun777的博客 5501

iOS多线程编程三:Operation和OperationQueue

概述 本文是多线程的第三篇文章,主要讲解Operation和OperationQueue。看资料的时候发现了一篇特别好的教程,随性就翻译一下,权当自己做个总结。本文主要内容翻译自raywenderlich的operation and operationqueue tutorial in swift。原文链接点这里。 不管是在Mac还是iO...

weixin_33806509的博客 371

华为Atlas200DK实战指南:从零搭建AI开发环境到人像语义分割模型部署

本文提供了一份详尽的华为Atlas 200DK AI开发环境搭建与模型部署实战指南。文章采用合设环境方案,从SD卡准备、系统镜像烧录、网络配置到必备工具安装,逐步引导开发者完成环境搭建。核心部分详细讲解了如何利用华为ATC工具将TensorFlow模型转换为昇腾专用格式,并最终成功编译和运行人像语义分割模型,实现实时人像识别效果。

weixin_29309213的博客 356

iOS应用性能调优的25个建议和技巧

写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员。这是他的个人网站:http://www.marcelofabri.com/,你还可以在Twitter上关注@marcelofabri_。 性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论。然而

1万+

通达信浮筹多空波段抓牛擒龙指标公式源码

VAR33:=VA3>=REF(VA4,1) AND C<REF(C,1) AND VAR19=60 AND VAR18=0 AND 活跃线>=REF(活跃线,1) AND VA12<REF(VA13,1);DRAWTEXT(VAR28 AND COUNT(VAR28,30)=1,65,' ★超涨注意风险'),COLOR0000FF;DRAWTEXT(VAR26 AND COUNT(VAR26,30)=1,90,' ←继续等'),COLOR00FFFF;浮筹线:VA3,COLORFF00FF;

2401_86043146的博客 5260

关于自制的《航空学报》latex模板(非官网模板)

《航空学报》的官网只提供了word模板,并且该期刊投稿只需要pdf版本不需要源文件。为方便latex爱好者撰写论文,提供该模板及说明给广大科研人士~

qq_37105055的博客 4692

iOS内存优化——OperationQueue悄悄给你挖的坑

这篇文章是对以前我们的APP做过的一次内存优化的介绍,场景是在大批量(数千至上万)的小文件(JSON、图片)数据下载的情况,使用NSOperationQueue和dispatch_global_queue的一些注意点,有类似大批量数据的上传或下载需求的童鞋可以参考一下。 一、基本概念 1.队列。 使用场景 在iOS的开发中,我们经常会需要处理一些耗时操作,比如网络请求、文件读写、数据库增

wentianen的博客 2574

目标检测 RT-DETR(2023)详细解读

在使用了这个技巧后,显然训练过程中,类别的标签不再是此前的0和1离散值,而是0~1的连续值。关于 Query Selection(查询向量选择),大家应该并不陌生,这个方法可谓在DETR领域大杀四方,如DAB-DETR对查询向量进行重构理解,将其解释为Anchor,DN-DETR通过查询降噪来应对匈牙利匹配的二义性所导致的训练时间长的问题,DINO提出从Encoder中选择Top-k特征进行学习等一系列方法,这都无疑向我们证明,查询向量很重要,选择好的Query能够让我们事半功倍。在RT-DETR中,

qq_51352130的博客 5869

iOS 并发编程之 Operation Queues

转载自 雷纯锋的技术博客,便于学习查找,不做商业用途 现如今移动设备也早已经进入了多核心 CPU 时代,并且随着时间的推移,CPU 的核心数只会增加不会减少。而作为软件开发者,我们需要做的就是尽可能地提高应用的并发性,来充分利用这些多核心 CPU 的性能。在 iOS 开发中,我们主要可以通过 Operation Queues、Dispatch Queues 和 Dispatch So

xianghuibeijing的专栏 885

ubuntu下编译qtwebengine

ubuntu qtwebengine

tianyu的专栏 - Linux site:blog.youkuaiyun.com/wishfly 1463

Qt5.14.2开发Mqtt应用程序

然后,你就做不下去了…很明显,大部分博主写的东西不是缺头就是缺尾,带偏了许多读者。,因此我们需要clone的是这个分支版本,而不是这个默认的。然后将编译产物中include里的所有.h文件复制到。下载完后直接默认安装即可,这一步没什么好说的。看到了没,这个才是正确的操作方式,而主线的。信号来判断,自行实现自己的槽函数。然后选择构建方式,这里我选择的是。信号来判断自行实现自己的槽函数。信号来判断自行实现自己的槽函数。源代码,如下图所示,双击打开。收到下行消息时,可以通过连接。

Bruce.yang的嵌入式之旅 2310

iOS并发编程(上)-- NSOperation queue

并发是多件事情同时发生的一个概念。 在过去,在应用中引入并发就需要创建一个或者多个额外的线程。不幸的是,写线程代码是一个挑战。线程是低层次工具必须手动的管理。给定应用可选的线程数会基于当前系统负载和硬件动态的改变。实现一个正确的线程方案变得额外的困难,很难达到。并且,线程同步机制的使用会增加软件的复杂度和风险而且还不能保证提升性能。 iOS和OS X都提供了一个比传统基于线程更加异步的

MakeCodeClear的专栏 1035

【产品经理修炼之道】-如何搭建企业级账务系统?

笔者公司的业务模式具有一定的独特性,不同于我们常见的市面上供应链类公司的进销存模式。公司主要为各大银行和金融机构提供信贷领域的风控服务,客户主要通过请求公司的数据产品接口产生费用,可以简单地理解为请求一次接口收费0.5元,一个月若是有1w人请求同一个接口则公司需要收费5000元。

xiaoli8748的专栏 5405

关于iOS多线程的总结

关于iOS多线程的总结 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实际使用中感受它们的区别。还有一点需要说明的是,这篇文章将会使用Swift和Objective-c两种语言讲解,双语幼儿园。OK,let's begin! 概述 这篇文章中,我不会说多线程是什么、线程和进程的区别、多线程有...

a359798678的博客 87

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

IOS开发,多线程,GDC ,线程 详解

NSRunLoop 循环机制 NSRunTime 循环时刻 什么时候创建子线程是有条件的 1.进行大量数据运算   for 数据库查询 select 将 select放在子线程中 2.网络请求 异步(将异步放在子线程中) IOS中关于UI的添加必须在主线程中操作 - (void)viewDidLoad {     [super viewDidLoa

司徒新新的专栏 2793

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

iOS 多线程

在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实际使用中感受它们的区别。还有一点需要说明的是,这篇文章将会使用 Swift 和 Objective-c 两种语言讲解,双语幼儿园。OK,let's begin! 概述 这篇文章中,我不会说多线程是什么、线程和进程的区别、多线程有什

Yin_Xian的博客 549

多线程与GCD

//——————————————————————NSThread多线程的开启———————————————————————————————— // 1.第一种开启新的线程调用 mutableThread NSThread *thread=[[NSThread alloc] initWithTarget:self selector:@selector(mutableThread) obje

Default is Zero. 2265

关于iOS多线程

转自 伯恩的遗产http://www.jianshu.com/p/0b0d9b1f1f19 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实际使用中感受它们的区别。还有一点需要说明的是,这篇文章将会使用 Swift 和 Objective-c 两种语言讲解,双语幼儿园。OK,let's begin! 概...

weixin_30730151的博客 85

46.多线程

1.多线程的基本概念 程序:由源代码生成的可执行应用(QQ.app),进程:一个正在运行的程序可以看做一个进程,进程拥有独立运行所需要的全部资源,线程:程序中独立运行的代码段(接收QQ消息的代码) 每个正在运行的程序(即进程)至少有一个线程,进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行 只有一个主线程的程序叫单线程程序,主线程负责执行程序的所有代码(UI展现和数据刷新,网络

yunyuan_的博客 450

关于iOS多线程,你看我就够了

在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实际使用中感受它们的区别。还有一点需要说明的是,这篇文章将会使 用 Swift 和 Objective-c 两种语言讲解,双语幼儿园。OK,let't begin! 概述 这篇文章中,我不会说多线程是什么、线程和进程的区别、多线程有什么用,当然我也不会说什么是串行、什么是并行...

weixin_33947521的博客 84

简述多线程的作用以及什么地方用到多线程

1, 多线程的作用:可以解决负载均衡问题,充分利用CPU的资源,为了提高Cpu的使用,采用多线程的方法去同时完成几件事情而互不干扰 2. 大多数的情况下, 使用多线程 主要是需要处理大量的IO操作或处理的情况需要花大量的时间等; 3. iOS 有三种主要的方法创建线程:1. NSTread, 2.NSOperationQueue, 3, GCD 4. 解决方案:使用线程锁,锁是线程同步工

今天明天 1万+

GCD(1)

#import "ViewController.h" int threadNumber = 0; int newThingNumber = 0; @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do...

weixin_30412577的博客 91

ios 多线程

一,多线程概述 1. 进程和线程 计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行.假定工厂的电力有限,一次只能给一个车间使用,也就是说,一个车间开工的时候,其他车间都必须停工,背后的含义就是,单个CPU一次只能运行一个任务.进程就好比工厂的车间,它代表CPU所能处理的单个任务,任一时刻,CPU总是运行一个进程,其他进程处于非运行状态.一个车间里,可以有很多工人,他们协

盛夏的果实 660

iOS 线程

1.3中方式: NShread,GCD(Grand Central Dispatch),NSOperation&NSOperationQueue 2.创建/开启线程: NSSTread: // 创建 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:nil]

suke3533的博客 328

iOS 多线程基础

系列文章: 多线程 多线程 pthread、NSThread 多线程 GCD 多线程 NSOperation 多线程运用 原理 优缺点 主线程 面试题: iOS NSThread NSOperation GCD的优缺点 NSOperation 相比于 GCD 有哪些优势? 你的项目什么时候选择使用GCD,什么时候选择NSOperation? 线程间怎么通信? Pthre...

weixin_34248849的博客 91

iOS子线程更新UI到主线程的三种方法

http://blog.youkuaiyun.com/cordova/article/details/54933729简单说将代码同步到主线程执行的三种方法如下:// 1.NSThread [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; - (void)updateUI { ...

opentogether的博客 3043
上一篇: 聊聊iOS中TCP / UDP 协议
下一篇: 程序猿们,iOS中是有生命周期的
kaihaOS
博客等级 码龄11年 3粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值