# 10.2.3 并发控制

函数是编译器的编译单元，也是编译器的并发单元，可以通过编译参数 `-c` 指定编译器编译的并发数量。并发控制的代码如下：

```go
func compileFunctions() {
    if len(compilequeue) == 0 {
        return
    }

    // 控制编译顺序
    if race.Enabled {
        // Randomize compilation order to try to shake out races.
        tmp := make([]*ir.Func, len(compilequeue))
        perm := rand.Perm(len(compilequeue))
        for i, v := range perm {
            tmp[v] = compilequeue[i]
        }
        copy(compilequeue, tmp)
    } else {
        // Compile the longest functions first,
        // since they're most likely to be the slowest.
        // This helps avoid stragglers.
        sort.Slice(compilequeue, func(i, j int) bool {
            return len(compilequeue[i].Body) > len(compilequeue[j].Body)
        })
    }

    // We queue up a goroutine per function that needs to be
    // compiled, but require them to grab an available worker ID
    // before doing any substantial work to limit parallelism.
    workerIDs := make(chan int, base.Flag.LowerC)
    for i := 0; i < base.Flag.LowerC; i++ {
        workerIDs <- i
    }

    var wg sync.WaitGroup
    var asyncCompile func(*ir.Func)
    asyncCompile = func(fn *ir.Func) {
        wg.Add(1)
        go func() {
            worker := <-workerIDs
            ssagen.Compile(fn, worker)
            workerIDs <- worker

            // Done compiling fn. Schedule it's closures for compilation.
            for _, closure := range fn.Closures {
                asyncCompile(closure)
            }
            wg.Done()
        }()
    }

    types.CalcSizeDisabled = true // not safe to calculate sizes concurrently
    base.Ctxt.InParallel = true
    for _, fn := range compilequeue {
        asyncCompile(fn)
    }
    compilequeue = nil
    wg.Wait()
    base.Ctxt.InParallel = false
    types.CalcSizeDisabled = false
}
```

可见 `-c` 控制并发数量，然后函数 `asyncCompile` 通过 `workerIDs` 与 `sync.WaitGroup` 进行并发同步。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocompiler.shizhz.me/10.-golang-bian-yi-qi-han-shu-bian-yi-ji-dao-chu/10.2.3-bing-fa-kong-zhi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
