DispatchQueue Sync Concurrent

时间:2017-06-08 07:24:32

标签: ios swift grand-central-dispatch

好的,所以我经历了大量的问题和答案,我知道它的理解,但是当我尝试一些代码时,我得到的结果并不符合这些理论。

到目前为止我理解的是:

  1. 同步:一旦块内的所有任务都将被执行,控制将返回。
  2. 异步:控件将在块被击中后立即返回。
  3. 这是看起来很好的部分。 现在是棘手的部分

    1. Serial:任务将在块内以串行方式执行。 Q1:这适用于区块内的任务吗?因为它已经在所有场景中发生。同样对于同步串行队列,在不同块中添加任务无关紧要,因为一旦完成第一个任务,控制将返回。
    2. EG -

       let syncQ = DispatchQueue(label:"xyz") // by default it is serial
        syncQ.sync{
            for _ in 0...10{
                print("ABC")
            }
        }
      
        syncQ.sync{
            for _ in 0...10{
                print("XYZ")
            }
        }
      

      预期输出:ABC * 10,XYZ * 10 这很好。

      现在当我引入并发串行Q时,输出是相同的。所以我的问题是并发队列说任务将在同一时间或同时完成,它不会发生。

      例如 -

      let syncConc = DispatchQueue(label:"con",attributes:.concurrent)
      syncConc.sync{
             for _ in 0...10{
                print("XYZ")
             }
      
             for _ in 0...10{
                print("ABC")
             }
      
      }
      
      
        syncConc.sync{
             for _ in 0...10{
                print("HHH")
             }
      
             for _ in 0...10{
                print("XXX")
             }
      
      }
      

      输出:XYZ * 10,ABC * 10,HHH * 10,XXX * 10

      所以似乎同步并发队列,就像串行队列一样,并且只有这样才能进行并发操作,如果我们在动作之间抛出一个异步队列。 所以我无法理解,并发类型的串行队列的目的是什么。

      如果有人能提供编码示例,我将非常感激,因为我已经了解它的理论和工作。 非常感谢。

3 个答案:

答案 0 :(得分:2)

问题在于您混淆了队列类型和执行模型。

有串行和并发队列,您可以同步或异步地将任务分派到两种类型。

队列可以是:

  • 串行 -> 一次只执行一项任务
  • 并发 -> 可以同时运行多个任务

我们可以将任务提交到队列:

  • 同步 -> 调用者需要等到该任务返回
  • 异步 -> 调用者代码无需等待任务完成即可重新获得控制权

总结一下:

  • 队列的串行或并发类型决定了它是否可以同时执行一个或多个任务
  • 同步或异步调度任务确定调用者的代码何时重新获得控制

答案 1 :(得分:1)

实际上,看起来在您的代码中,当您在并发队列(第二个代码段)中执行任务时,您通过同步块调度任务,因此将根据同步行为阻止当前线程。

"同步:一旦块内的所有任务都将被执行,控制权将返回。“

test: function(req, res) {
        sails.log("req.params = " + JSON.stringify(req.params.all()));
        if (req.method == "GET"){
            var value1 = req.param("value1");
            Test.findOne({"value1": value1).exec(function (err, value1){
                if(err) {
                    sails.log(err);
                    return res.serverError(err);
                }
                if(!value1){
                    //Some error
                }
                return res.ok(value1);
            });
        } else {
            var wrongHttpMethod = req.__('Wrong HTTP method');
            return res.notFound(wrongHttpMethod);
        }
    }

所以,在这种情况下,首先suncConc队列将调度第一个同步块,现在因为它是阻塞调用,下一个任务不会立即调度,它将被调度,一旦第一个将完成然后它将在suncConc队列中调度,并再次使用阻塞调用执行。

现在,让我来看看你的问题

"现在当我引入并发串行Q时,输出是相同的。所以我的问题是,并发队列说任务将在同一时间或同时完成,但它不会发生。"

是的,同步操作也可以同时执行,但只有在不阻塞当前线程的情况下立即调度这两个调用时才可以执行。检查以下片段,从不同的队列调度两个同步任务,因此它将同时执行。

   let syncConc = DispatchQueue(label:"con",attributes:.concurrent)

   syncConc.sync{
      for _ in 0...10{
        print("XYZ")
      }

      for _ in 0...10{
        print("ABC")
      }
   }


   syncConc.sync{
      for _ in 0...10{
        print("HHH")
      }

      for _ in 0...10{
        print("XXX")
      }
   }

执行代码&看到所有理论将按预期应用的魔力:)

答案 2 :(得分:-1)

能够看到串行/并发队列和同步/异步方法之间的差异以及如何将它们分派到队列中,尝试使用Playground上的下一个片段。

import PlaygroundSupport
import Dispatch
PlaygroundPage.current.needsIndefiniteExecution = true

let q = DispatchQueue(label: "concurrect queue", qos: .background, attributes: .concurrent)

func runner0(queue: DispatchQueue) {
    for _ in 1..<10 {
        let result = queue.sync { ()->Int in
            usleep(100)
            return 0
        }
        DispatchQueue.main.async {
            print(result, "-")
        }
    }
}

func runner1(queue: DispatchQueue) {
    for _ in 1..<10 {
        let result = queue.sync { ()->Int in
            usleep(100)
            return 1
        }
        DispatchQueue.main.async {
            print("-", result)
        }
    }
}

let arr = [runner0, runner1]

DispatchQueue.concurrentPerform(iterations: 2) { (i) in
    arr[i](q)
}

我们有一个并发队列,其中两个不同的运行器同步调度任务。如您所见,并发队列中的所有任务同时执行,然后在串行队列上串行(异步)打印结果。

我希望,这有助于您了解它是如何运作的。

我的游乐场打印

- 1
0 -
- 1
0 -
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
0 -
- 1
0 -
- 1
- 1

通过更改其定义,让队列成为串行

let q = DispatchQueue(label: "serial queue")

并比较我们的结果

0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1
0 -
- 1