设为首页 加入收藏

TOP

go语言之并发(二)
2017-09-30 13:56:59 】 浏览:9148
Tags:语言 并发
是个通用的解决方法。

 多路复用技术可以用来整合多个通道。提升性能和操作的便捷。配合其他的模式使用有很大的威力。

3.Future技术

        Future是一个很有用的技术,我们常常使用Future来操作线程。我们可以在使用线程的时候,可以创建一个线程,返回Future,之后可以通过它等待结果。  但是在协程环境下的Future可以更加彻底,输入参数同样可以是Future的。

Go语言并发之美

调用一个函数的时候,往往是参数已经准备好了。调用协程的时候也同样如此。但是如果我们将传入的参 数设为通道,这样我们就可以在不准备好参数的情况下调用函数。这样的设计可以提供很大的自由度和并发度。函数调用和函数参数准备这两个过程可以完全解耦。 下面举一个用该技术访问数据库的例子。

//一个查询结构体
typequery struct {
         //参数Channel
         sql chan string
         //结果Channel
         result chan string
}
//执行Query
funcexecQuery(q query) {
         //启动协程
         go func() {
                   //获取输入
                   sql := <-q.sql
                   //访问数据库,输出结果通道
                   q.result <- "get" + sql
         }()
}
funcmain() {
         //初始化Query
         q :=
                   query{make(chan string, 1),make(chan string, 1)}
         //执行Query,注意执行的时候无需准备参数
         execQuery(q)
         //准备参数
         q.sql <- "select * fromtable"
         //获取结果
         fmt.Println(<-q.result)
}

 

        上面利用Future技术,不单让结果在Future获得,参数也是在Future获取。准备好参数后,自动执行。Future和生成器的区别在 于,Future返回一个结果,而生成器可以重复调用。还有一个值得注意的地方,就是将参数Channel和结果Channel定义在一个结构体里面作为 参数,而不是返回结果Channel。这样做可以增加聚合度,好处就是可以和多路复用技术结合起来使用。

        Future技术可以和各个其他技术组合起来用。可以通过多路复用技术,监听多个结果Channel,当有结果后,自动返回。也可以和生成器组合使用,生 成器不断生产数据,Future技术逐个处理数据。Future技术自身还可以首尾相连,形成一个并发的pipe filter。这个pipe filter可以用于读写数据流,操作数据流。

        Future是一个非常强大的技术手段。可以在调用的时候不关心数据是否准备好,返回值是否计算好的问题。让程序中的组件在准备好数据的时候自动跑起来。

4.并发循环

       循环往往是性能上的热点。如果性能瓶颈出现在CPU上的话,那么九成可能性热点是在一个循环体内部。所以如果能让循环体并发执行,那么性能就会提高很多。

Go语言并发之美

要并发循环很简单,只有在每个循环体内部启动协程。协程作为循环体可以并发执行。调用启动前设置一个计数器,每一个循环体执行完毕就在计数器上加一个元素,调用完成后通过监听计数器等待循环协程全部完成。

//建立计数器
sem :=make(chan int, N); //FOR循环体
for i,xi:= range data { //建立协程
    go func (i int, xi float) { doSomething(i,xi); //计数
        sem <- 0; } (i, xi); } // 等待循环结束
for i := 0; i < N; ++i {
<-sem }

    上面是一个并发循环例子。通过计数器来等待循环全部完成。如果结合上面提到的Future技术的话,则不必等待。可以等到真正需要的结果的地方,再去检查数据是否完成。

        通过并发循环可以提供性能,利用多核,解决CPU热点。正因为协程可以大量创建,才能在循环体中如此使用,如果是使用线程的话,就需要引入线程池之类的东西,防止创建过多线程,而协程则简单的多。

5.ChainFilter技术

      前面提到了Future技术首尾相连,可以形成一个并发的pipe filter。这种方式可以做很多事情,如果每个Filter都由同一个函数组成,还可以有一种简单的办法把他们连起来。

Go语言并发之美

由于每个Filter协程都可以并发运行,这样的结构非常有利于多核环境。下面是一个例子,用这种模式来产生素数。

// Aconcurrent prime sieve
packagemain
// Sendthe sequence 2, 3, 4, ... to channel 'ch'.
funcGenerate(ch chan<- int) {
         for i := 2; ; i++ {
                  ch<- i // Send 'i' to channel 'ch'.
         }
}
// Copythe values from channel 'in' to channel 'out',
//removing those divisible by 'prime'.
funcFilter(in <-chan int, out chan<- int, prime int) {
         for {
                   i := <-in // Receive valuefrom 'in'.
                   if i%prime != 0 {
                            out <- i // Send'i' to 'out'.
                   }
         }
}
// Theprime sieve: Daisy-chain Filter processes.
funcmain() {
         ch := make(chan int) // Create a newchannel.
         go Generate(ch)      // Launch Generate goroutine.
         for i := 0; i < 10; i++ {
                   prime := <-ch
                   print(prime, "\n")
                   ch1 := make(chan int)
                   go Filter(ch, ch1, prime)
                   ch = ch1
         }
}

       上面的程序创建了10个Filter,每个分别过滤一个素数,所以可以输出前10个素数。   

      Chain-Filter通过简单的代码创建并发的过滤器链。这种办法还有一个好处,就是每个通道只有两个协程会访问,就不会有激烈的竞争,性能会比较好

6.共享变量

        协程之间的通信只能够通过通道。但是我们习惯于共享变量,而且很多时候使用共享变量能让代码更简洁。比如一个Server有两个状态开和关。其他仅仅希望

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇golang 标准库间依赖的可视化展示 下一篇Golang控制goroutine的启动与关闭

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目