GO语言并发

本文深入探讨了Go语言实现高并发的技术原理,包括goroutine的工作机制、通道(channel)的使用方式及其特性,以及sync包提供的同步原语。通过具体代码示例展示了如何利用这些特性进行高效并发编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是高并发
https://studygolang.com/articles/10939#reply0

**重点内容**Go语言高并发优势的原因:
goroutine每个实例占据的栈内存极小,故减少了创建和销毁的开销,是制造Go号称的高并发的根本原因。

并发不是并行
并发:主要由切换时间片来实现”同时”运行
并行:直接利用多核实现多线程的运行,但是Go可以设置使用核数,以发挥多核计算机的能力

goroutine奉行通过通信来共享内存,而不是共享内存来通信

当main()结束的时候他不会管你的线程是否结束

package main

import "fmt"

func Go(){
  fmt.Println("GO GO GO!")
}

func main(){
  go Go()
}

例如如上函数就不会有输出

Channel
goroutine沟通的桥梁
channel创建出来都是双向的
但是可以把她设置成单向的

引用类型也就是传入数据的改变会影响原数据
默认是阻塞的
小例子1

package main

import "fmt"

func main(){
  c:=make(chan bool)
  go func(){
  fmt.Println("GO GO GO!")
  c<-true//store
  }()
  <-c//get,will wait for goroutine's store or it will block
}

迭代取

package main
import "fmt"
func main(){
  c:=make(chan bool)
  go func(){
  fmt.Println("GO GO GO!")
  c<-true//store
  close(c)//close the channel
  }()
  for v:=range c{//won't stop until close the channel successful
   fmt.Println(v)
  }
}

关于缓存
可以设置缓存,在未被填满前不会发生阻塞,也就是说异步的,无缓存是同步阻塞的

有缓冲:放入数据的操作c<- 0先于取数据操作 <-c
无缓冲:必须保证取操作<-c 先于放操作c<- 0
http://studygolang.com/articles/152

package main
import "fmt"
import "runtime"
func main(){

runtime.GOMAXPROCS(runtime.NumCPU())//return the num of CPU
    c:=make(chan bool,10)
    for i:=0;i<10;i++{
    go Go(c,i)
   }

   for i:=0;i<10;i++{
   <-c
}
}

func Go(c chan bool,index int) {
  a:=1
  for i:=0;i<10000000;i++{
  a+=i
  }
  fmt.Println(index,a)
  c<-true  
}

关于sync包

package main

import "fmt"
import "runtime"
import "sync"

func main(){

runtime.GOMAXPROCS(runtime.NumCPU())//return the num of CPU
    wg:=sync.WaitGroup{}
    wg.Add(10)
    for i:=0;i<10;i++{
    go Go(&wg,i)
   }

   wg.Wait()
}

func Go(wg *sync.WaitGroup,index int) {
  a:=1
  for i:=0;i<10000000;i++{
  a+=i
  }
  fmt.Println(index,a)
  wg.Done()
}

多个Channel的发送与接收Select

package main

import "fmt"


func main(){

  c1,c2:=make(chan int),make(chan string)
  o:=make(chan bool)
  go func(){
     a,b:=false,false//ensure that only write once to channel
     for{
        select{
          case v,ok:=<-c1:
              if !ok{
                   if !a{
                   o<-true
                   a=true
                   }
                   break
                }
               fmt.Println("c1",v)
           case v,ok:=<-c2://v and ok are local variable   
               if !ok&&!b{
                     if !b{
                   o<-true
                   b=true
                   }
                     break
                    }
           fmt.Println("c2",v)
          }
     }
   }()

   c1<-1
   c2<-"hi"
   c1<-3
   c2<-"hello"
   close(c1)
   close(c2)

   <-o//ensure that there has one routine has finished before the main

}

select作为发送者

package main
import "fmt"
func main(){

  c:=make(chan int)

  go func(){
     for v:=range c{
      fmt.Println(v)
       }
  }()

  for{
    select{
     case c<-0:
     case c<-1:
     }
  }      
}

空的selece{}就一直阻塞

关于select设置定时
例子

package main

import "fmt"
import "time"

func main(){

  c:=make(chan int)
  select{
   case v:=<-c:
     fmt.Println(v)
    case <-time.After(3*time.Second):
     fmt.Println("Timeout")
   }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值