这里简单的介绍一下go中的关于多线程的知识。
Go中的多线程
一、go中简单的并发例子
package main import ( "fmt" "time" ) func Add(x, y int) { z := x + y fmt.Print(z, " ") } func main() { for i := 0; i < 10; i++ { go Add(i, i) } time.Sleep(1 * time.Second) // 睡眠一秒 fmt.Println("hello world") }
运行的结果,每次都可能不一样:
0 6 2 12 8 4 16 10 14 18 hello world
二、go中的并发通信
channel是Go语言在语言级别提供的goroutine间的通信方式。channel是类型相关的。也就是说,一个channel只能传递一种类型的值,这个类型需要在声明channel时指定。
package main import ( "fmt" "time" ) func Count(ch chan int) { ch <- 1 fmt.Println("Counting") } func main() { chs := make([]chan int, 10) for i := 0; i < 10; i++ { chs[i] = make(chan int) go Count(chs[i]) } for _, ch := range(chs) { fmt.Print(<- ch, " ") } time.Sleep(1 * time.Second) }
运行的结果,每次可能不一样:
Counting 1 1 1 1 1 Counting Counting Counting Counting 1 1 1 1 1 Counting Counting Counting Counting Counting
三、go中的select的使用
Go语言直接在语言级别支持 select 关键字,用于处理异步IO问题。
package main import ( "fmt" "time" ) func method1(ch chan string) { time.Sleep(1 * time.Second) ch <- "one" } func method2(ch chan string) { time.Sleep(2 * time.Second) ch <- "two" } func main() { c1 := make(chan string) c2 := make(chan string) go method1(c1) go method2(c2) for i := 0; i < 2; i++ { select { case msg1 := <- c1: fmt.Println("received1: ", msg1) case msg2 := <- c2: fmt.Println("received2: ", msg2) } } }
运行的结果如下:
四、go中的sync.Mutex互斥锁
package main import ( "fmt" "sync" "time" ) // SafeCounter 的并发使用是安全的。 type SafeCounter struct { v map[string]int mux sync.Mutex } // Inc 增加给定 key 的计数器的值。 func (c *SafeCounter) Inc(key string) { c.mux.Lock() // Lock 之后同一时刻只有一个 goroutine 能访问 c.v c.v[key]++ c.mux.Unlock() } // Value 返回给定 key 的计数器的当前值。 func (c *SafeCounter) Value(key string) int { c.mux.Lock() // Lock 之后同一时刻只有一个 goroutine 能访问 c.v defer c.mux.Unlock() return c.v[key] } func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i < 1000; i++ { go c.Inc("somekey") } time.Sleep(time.Second) fmt.Println(c.Value("somekey")) // 1000 }