Go语言中的多线程

goroute详解

  • 获取和设置当前runtime可用的最大核心数:
    1
    2
    3
    4
    5
    6
    7
    func main() {
    // 返回当前主机的cpu核心数
    num := runtime.NumCPU()
    // 设置当前runtime可用的最大核心数
    runtime.GOMAXPROCS(num)
    fmt.Printf("max cup :%v\n", num)
    }

多线程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 多线程 编译时建议带上参数-race,可以帮助检测函数中是否有锁竞争  go build -race xx/xxx/xxx/main

var (
m = make(map[int]int)
lock sync.Mutex
)

func calc(c int) {
num := 1
for i := 1; i < c; i++ {
num *= i
}

lock.Lock()
m[c] = num
lock.Unlock()
}

func main() {
for i := 0; i < 10; i++ {
go calc(i)
}
time.Sleep(time.Second)
lock.Lock()
for k, v := range m {
fmt.Printf("k:%v,v:%v\n", k, v)
}
lock.Unlock()
}

channel的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 如果存放的元素超过了channel定义的长度,则会处于阻塞状态,直到channel内的元素被取出

func test1() {
var m chan int
m = make(chan int, 10)
m <- 1
m <- 2
m <- 3

a := <-m
fmt.Printf("a:%d\n", a)
}

func test2() {
var c chan map[string]string
c = make(chan map[string]string, 10)
m := make(map[string]string, 10)
m["m1"] = "01"
m["m2"] = "02"

c <- m

v := <-c
fmt.Printf("v:%v\n", v)

}

func test3() {
var c chan student
c = make(chan student, 10)
s := student{
name: "张三",
}
c <- s

v := <-c
fmt.Printf("v:%v\n", v)

}

func main() {
test1()
test2()
test3()
}

在gorutine中使用channel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func write(c chan int) {
// 如果存放的元素超过了channel定义的长度,则会处于阻塞状态,直到channel内的元素被取出
for i := 0; i < 100; i++ {
c <- i
fmt.Println("put data:", i)
}
}

func read(c chan int) {
for {
var b int
b = <-c
fmt.Println("pop data:", b)
time.Sleep(time.Millisecond * 100)
}
}

func main() {
var c chan int
c = make(chan int, 10)
go write(c)
go read(c)

time.Sleep(time.Second * 10)

}

多个goroutine并发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
func initData(c chan int) {
for i := 0; i < 10000; i++ {
c <- i
}
close(c)
}

func calc(takeChan chan int, result chan int, exit chan bool) {
flag := true
for v := range takeChan {

for i := 2; i < v; i++ {
if v%i == 0 {
flag = false
break
}
}
if flag {
result <- v
}
flag = true
}
exit <- true
fmt.Println("exit-----------------------------------------------------")
}

func read(result chan int) {
for v := range result {
fmt.Println("result:", v)
}
}

func main() {
var intChan chan int
var resultChan chan int
var exitChan chan bool
intChan = make(chan int, 1000)
resultChan = make(chan int, 1000)
exitChan = make(chan bool, runtime.NumCPU())
go initData(intChan)
for i := 0; i < runtime.NumCPU(); i++ {
go calc(intChan, resultChan, exitChan)
go read(resultChan)
}
for i := 0; i < runtime.NumCPU(); i++ {
fmt.Printf("**************************wait goroute:%d************************\n", i)
<-exitChan
}
close(resultChan)
close(exitChan)
}

channel使用完要关闭:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
var c chan int
c = make(chan int, 10)
for i := 0; i < 10; i++ {
c <- i
}

close(c)
for {
v, ok := <-c
if ok == false {
fmt.Println("channel is colse!")
break
}
fmt.Println(v)
}
}

```

### select关键字的使用:

func main() {
var ch chan int
var ch2 chan int
ch = make(chan int, 10)
ch2 = make(chan int, 10)
go func() {
for i := 0; i < 10; i++ {
ch <- i
ch2 <- i * i
time.Sleep(time.Second)
}
}()

for {
    select {
    case v := <-ch:
        fmt.Println(v)
    case v := <-ch2:
        fmt.Println(v)
    default:
        fmt.Println("get data timeout")
        time.Sleep(time.Second)
    }
}

}

```