使用GCD

问题描述

我刚刚学习Swift,并且正在查看Grand Central dispatch(GCD),以完成一些cpu密集型任务。 (我相信)这是我不解的所有相关代码片段:

// global declarations
var digits        = [Int]()    // where the square's digits reside
var perm_q        = [[Int]]()  // where we accumulate permutations to check later
Let perm_q_max    = 1000       // how many permutations we queue before checking them
var enq_count     = 0          // how many times we've called check_squares
var N             = 3          // size of N x N square
let work_q = dispatchQueue.global()  // returns a global,concurrent dispatch queue
let work_g = dispatchGroup()         // returns a group we put all our work into

// func which is enqueued onto a GCD queue
func check_squares( cnt: Int,perm_ary: [[Int]]) { ... }

// func which calls enqueues check_squares() onto global GCD queue
func permute( k: Int,ary: inout [Int]) {

  if k == 1 {
    
    perm_q.append( ary)  // queue up this permutation for later magic checking

    // if we've queued up enough permutations,then dispatch check_squares()
    if ( perm_q.count >= perm_q_max) {
        enq_count += 1
        // --> let p: [[Int]] = perm_q  // make a local copy
        work_q.async( group: work_g) {      // assign work all to one group
        check_squares( cnt: enq_count,// check to see if any square is magic
                       perm_ary: p)
      }
      perm_q = [[Int]]()                  // clear out prevIoUs permutations
    }
  }

  else { ... }
}

// main
    
digits = Array( 1 ... ( N * N))  // fill digits with digits 1...N^2
permute( k: digits.count,ary: &digits)  // creates permutations and checks for magic squares

我遇到的问题是,除非我取消对permute()中work_q.async()上方的注释,否则当check_squares()启动时,ary的元素数为零,而我希望它包含1,000个元素。在将check_squres()放入全局异步队列中的GCD之后,我执行了perm_q = [Int],它清空了数组perm_q以准备收集下一个1,000个元素。

我猜想在开始check_squares()和清空perm_q之间存在竞争条件,并且清空发生在check_squares()开始之前,但是我对为什么发生这种竞赛感到困惑。我知道对check_squares()的调用将复制perm_q。

我想到的一种解释是,在GCD开始执行check_squares()之前,不会将perm_q复制到check_squares()的参数中。到这种情况发生时,perm_q已被清空。是将perm_q复制到ary中,而不是将check_squares放入队列时?将全局var perm_q的本地副本放入permute()的var p本地,并在入队期间将p传递到check_squares()会使本地var p停留在周围,因为队列中来自check_squares()的引用即使在置换后也能防止数组p消失()退出。听起来不错吗?

除了将perm_q的本地副本转换为p之外,还有一种处理此问题的首选方法吗?

谢谢埃里克

解决方法

除了制作本地副本...以外,还有处理此问题的首选方法吗?

赋予其他线程自己的本地副本的最简单方法是通过捕获列表:

queue.async(group: group).async { [array] in
    checkSquares(array)
}