Objective-C中的同步和异步调用与多线程之间有什么区别?

时间:2014-01-14 20:01:01

标签: ios objective-c multithreading asynchronous grand-central-dispatch

在最长的时间里,我认为异步是在后台线程上运行某些东西的同义词,而同步意味着在主线程上(阻止UI更新和交互)。我知道没有在主线程上运行昂贵的操作是因为它不允许在主线程被占用时发生UI动作,但为什么同步麻烦?

但是,我注意到你可以在主线程上进行异步调用,并在后台线程上进行同步调用。

我总是听到人们说不要同步或在主线程上使用昂贵的调用,因为它会阻止用户的UI。这两个不同的问题我应该确保我不做吗?有什么区别?

6 个答案:

答案 0 :(得分:101)

当您同步调用某些内容时,这意味着启动该操作的线程将在继续之前等待任务完成。异步意味着它不会等待。

话虽如此,当人们建议您异步执行一些缓慢或昂贵的过程时,他们隐含地建议您不仅应该异步运行它,而且应该在后台线程上执行此操作。目标是释放主线程,以便它可以继续响应用户界面(而不是冻结),因此您将异步调度到后台线程。

所以,有两个部分。首先,使用GCD作为示例,您获取后台队列(获取一个全局后台队列,或创建自己的队列):

// one of the global concurrent background queues

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// or you could create your own serial background queue:
//
// dispatch_queue_t queue = dispatch_queue_create("com.domain.app.queuename", 0);

其次,您以异步方式将任务分派到该队列:

dispatch_async(queue, ^{
    // the slow stuff to be done in the background
});

操作队列的模式非常相似。创建操作队列并向该队列添加操作。

实际上,同步与异步的区别与主队列与后台队列的区别完全不同。但是当人们谈论"异步地运行一些缓慢的过程时,他们真的会说"在后台队列上异步运行一些缓慢的进程。"

答案 1 :(得分:27)

“同步”本质上意味着“按顺序排列。”基本上,当您执行同步操作时,稍后出现的所有内容都必须等待操作完成才能完成可以开始。

相反,“异步”或多或少意味着“不按顺序。”当您异步执行某些操作时,以下代码可以立即运行,异步操作将是运行一段时间...。它可能与另一个线程上的其余代码并行运行。它可能只是安排在同一个线程上的其他时间。

同步性的概念本身与特定线程没有任何关系。这是关于你是否必须等待手术完成。

主要线程在很大程度上涉及到Cocoa(Touch)程序。 AppKit在主线程上运行主事件循环,因此如果主线程正在等待操作完成,则它无法处理任何输入或更新UI。但是,如果您在后台线程上运行了一段代码,则运行同步代码将不会阻止主事件循环,因为它不是等待同步操作完成的主线程。

类似地,您在主线程上放置的后台线程长时间运行的异步操作可能会导致问题,因为后台线程不会等待操作完成,它仍然占用事件循环需要运行的主线程上的时间。

答案 2 :(得分:16)

让我们举一些简单的例子:

多线程异步调用:

// Methods gets called in different thread and does not block the current thread. 
[NSURLConnection sendAsynchronousRequest:request 
                                   queue:queue 
                       completionHandler:
    ^(NSURLResponse *response, NSData *data, NSError *error) {
}];

多线程同步调用:

//Do something
dispatch_sync(queue, ^{
    //Do something else
});
//Do More Stuff

在这里你做了//做某事//做其他事情//连续做更多的事情,即使在其他线程上做了别的事。

通常,当人们使用不同的线程时,整个目的是让某些东西可以在不等待的情况下执行。假设您要下载大量数据,但希望保持UI流畅。

因此,很少使用dispatch_sync。但它就在那里。我个人从未使用过。为什么不要求使用dispatch_sync的示例代码或项目。

使用一个线程进行异步调用:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0];

这里调用'doSomething'之前完成的当前runloop。换句话说,在调用'doSomething'之前,可以完成当前调用堆栈(当前方法返回)。

同一个线程的同步通话:

 [self doSomething];

我认为你不需要解释。

通常,异步活动与线程不同,但在iOS中,它们是使用这种方式实现的。它并非适用于所有语言。我们通常使用运行循环管理不同的异步任务。

答案 3 :(得分:4)

迅速3、4、4、2 同步 表示启动该操作的线程将等待任务完成,然后再继续。

DispatchQueue.main.sync {

}

异步 意味着在后台完成任务,并且可以在完成时通知您,这意味着它不会等待。

DispatchQueue.main.async {

}

答案 4 :(得分:3)

异步意味着脱节,同步意味着排队。您可以一次执行同步任务并阻止多个线程。

如果您在后台线程中并希望更新一大堆用户界面,则可以调用dispatch队列中的主线程。如果您调用dispatch_sync,那么您当前所在的代码将等待dispatch完成,从而阻止您所在的后台线程并在更新主线程时阻止该UI。

但是如果你调用dispatch_async,后台线程将继续列出其余代码,主线程将运行请求的dispatch块。

在主线程中也可以这样说。如果从主线程调用dispatch_sync到全局或自定义队列,它将在单独的线程中运行代码时阻塞主线程。我不能说我知道会使用哪种情况,但肯定是可能的。

每当你有计算代码,webservice代码,提取代码,以及不影响UI的东西时,最好在单独的线程中进行。对于这种东西,我会在全局线程中进行dispatch_async。然后,当代码完成后,我会在主线程中运行dispatch_async,告诉它用我刚刚计算的内容更新UI。

同步意味着阻止,异步意味着它将在稍后(可能是现在)完成,而不会阻止您当前正在做的事情。

答案 5 :(得分:2)

这个讨论几乎可以解答它: Asynchronous vs Multithreading - Is there a difference?

  

在一般情况下,异步调用不一定会创建新线程。这是实现它的一种方式,预先存在的线程池或外部进程是其他方式。它在很大程度上取决于语言,对象模型(如果有的话)和运行时环境。

     

异步只是意味着调用线程不会等待响应,异步活动也不会在调用线程中发生。

基本上,在等待加载某些内容时可能会发生其他活动,但它可能会也可能不会在单独的线程上完成。