Go goroutine

Concurrency

  • Goroutines 一个goroutines就是一个轻量(lightweight)的线程,语法很简单:
  go f(x,y,z)

这表示创建一个线程来执行f(x,y,z)函数。

**Note: **Goroutines run in the same address space, so access to shared memory must be synchronized.

  • Channels 这个差不多就是管道(pipe)了。可以往里面写东西,也可以读东西。
  ch <- v // send v to channel ch
  v := <- ch // retrive from ch and assign value to v

和slice,map一样,channel必须使用make来初始化。

  ch := make(chan int)

一段代码例子:

  package main

  import "fmt"

  func sum(s []int, c chan int) {
      sum := 0
      for _, v := range s {
          sum += v
      }
      c <- sum // send sum to c
  }

  func main() {
      s := []int{7, 2, 8, -9, 4, 0}

      c := make(chan int)
      go sum(s[:len(s)/2], c)
      go sum(s[len(s)/2:], c)
      x, y := <-c, <-c // receive from c

      fmt.Println(x, y, x+y)
  }
  • Buffered Channels Channels可以带buffer。在make()函数中,创建channel的时候第二个参数表示buffer的长度。
  ch := make(char int, 100)

往一个buffered channels发送数据的时候,当buffer是满的时候会block。在获取数据的时候,当buffer是空的时候会Block。

  • Range and Close 发送者可以关闭channels来表明已经没有数据要发送了。Receivers能够测试channel是否被关闭。语法如下:
  v,ok := <-ch

如果channels被关闭了,那么ok=false。可以使用for i := range c来从一个channel中读取数据,直到channel被关闭。

Note:Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.

  • Select select 语句用于让goroutine等待多个通信操作。一个selec会block直到其中一种case可以运行。如果有多种情况都可以可以执行的时候,随机来执行其中一种。官网,没有特别明白select的用处。
  package main

  import "fmt"

  func fibonacci(c, quit chan int) {
      x, y := 0, 1
      for {
          select {
          case c <- x:
              x, y = y, x+y
          case <-quit:
              fmt.Println("quit")
              return
          }
      }
  }

  func main() {
      c := make(chan int)
      quit := make(chan int)
      go func() {
          for i := 0; i < 10; i++ {
              fmt.Println(<-c)
          }
          quit <- 0
      }()
      fibonacci(c, quit)
  }
  • sync.Mutex 这个就是互斥了(mutual exclusion),官网Doc没有讲到如何在go中实现差不多join的函数。用了time.sleep来等待goroutines运行结束。下面使用一个链表的插入来演示其作用。
  type Node struct {
      value int
      next *Node
  }
  type LinkeList struct {
      mu sync.Mutex
        head *Node
      len int
  }
  func initList() *LinkList {
      return &LinkedList{sync.Mutex{},nil,0}
  }
  func (list *LinkedList) inertNode(value int) {
      var  = Node{value,int}
      list.mu.Lock() //上锁
      newNode.next =  list.head
      list.head = &newNode
      list.len++
      list.mu.Unlokc() //解锁
  }
  func (list *LinkedList) printList() {
      var temp = list.head
      for temp != nil {
          fmt.Println(temp.value)
          temp = temp.next
      }
  }
  func intserArray(list *LinkedList) {
      var nums = [1000]int
      for i:= 0; i < 1000; i++ {
          nums[i] = i
      }
      for _,v := range nums {
          list.insertNode(v)
      }
  }
  func main() {
      var list = initList()
      go insterArray(list)
      go insertArray(list)
      time.sleep(time.Second) //不用join,而是用sleep的方式来等待主线程运行结束
      fmt.Println(list.len)
  }

上述代码,如果不加锁的话,最后输出的链表长度会不等于2000。上锁才可以保持同步。

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇