14.11. 限制并发数

未匹配的标注

可以很轻松的实现一个带缓冲的通道(可以参见 14.2.5 章节),它的容量是并发请求的最大数目。下面的示例 max_tasks.go 没做任何事情,它包含了下列技巧:不超过 MAXREQS 的请求将被处理并且是同时处理,因为当通道 sem 的缓冲区全被占用时,函数 handle 被阻塞,直到缓冲区中的请求被执行完成并且从 sem 中删除之前,不能执行其他的请求。sem 就像一个 semaphore (信号量),表示一个在一定条件的程序中的一个标志变量的技术术语:由此得名。

Listing 14.16—max_tasks.go:

package main

const (

    AvailableMemory = 10 << 20

    // 10 MB, 示例

    AverageMemoryPerRequest = 10 << 10

    // 10 KB

    MAXREQS = AvailableMemory / AverageMemoryPerRequest 
    // 原文中说 MAXREQS 是 1000,实际计算是 1024 ,后面按照原文的 1000 来描述

)

var sem = make(chan int, MAXREQS)

type Request struct {

    a, b int

    replyc chan int

}

func process(r *Request) {

    // Do something 做任何事

    // 可能需要很长时间并使用大量内存或CPU

}

func handle(r *Request) {

    process(r)

    // 信号完成:开始启用下一个请求

    // 将 sem 的缓冲区释放一个位置

    <-sem

}

func Server(queue chan *Request) {

    for {

        sem <- 1

        // 当通道已满(1000 个请求被激活)的时候将被阻塞

        // 所以停在这里等待,直到 sem 有容量(被释放),才能继续去处理请求

        // (doesn’t matter what we put in it)

        request := <-queue

        go handle(request)

    }

}

func main() {

    queue := make(chan *Request)

    go Server(queue)

}

通过这种方式,程序中的协程通过使用缓冲通道(这个通道作为一个 semaphore 被使用)来调整资源的使用,实现了对内存等有限资源的优化。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/the-way-to-go/1...

译文地址:https://learnku.com/docs/the-way-to-go/1...

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~