Thread

前段时间看了golang.并行的模块停下来了,正好这个学期上操作系统,而且前段时间的五子棋设计的时候需要网络通信。多线程就成了必要的东西的了。是时候看看线程了。

在没有设计多线程之前,我们的程序是step by step的!

大程序往往会由许许多多的小程序组成,例如,Web服务器需要处理从浏览器发来的请求,并回复HTML页面。每个请求就像一个小程序。 web服务器能同时处理多个请求,这就需要并行的技术了。

在java中要使一个类的几个示例多线程运行,则类需要继承自Runnable类。然后用 Thread类来创建进程。(当然还有其他的方式).

在Go中,用goroutineschannels来支持并行.

Goroutines

对于goroutines:

A goroutine is a function that is capable of running concurrently with other functions.

要新建一个goroutine:

package main

import "fmt"
import "time"

func f(n int) {
	for i := 0; i < 10; i++ {
		fmt.Println(n, ":", i)
		time.Sleep(time.Millisecond * 1000)
	}
}

func main() {
	go f(0)
	var input string
	fmt.Scanln(&input)
}

上面的代码中有两个goroutine。第一个是个隐式的:main函数本身。第二个是我们用go f(0)创建的。 正常情况下,函数调用会执行完返回再进入下一行,但是有了goroutine,会马上执行下一行,不用等到函数返回。

这么看来,go语言的goroutine比java中的轻量了许多。也方便了不少。

channels

对于channels:

Channels provide a way for two goroutines to communicate with one another and synchronize their execution.

package main

import (
  "fmt"
  "time"
)

func pinger(c chan string) {
  for i := 0; ; i++ {
    c <- "ping"
  }
}

func printer(c chan string) {
  for {
    msg := <- c
    fmt.Println(msg)
    time.Sleep(time.Second * 1)
  }
}

func main() {
  var c chan string = make(chan string)

  go pinger(c)
  go printer(c)

  var input string
  fmt.Scanln(&input)
}

channal的声明就不说了,我们可以当c时一个容器,这里是string容器。 printer会输出c里的内容,而pinger书不断往容器里放入”ping”。当容器是空的时候,printer就会阻塞了.

对了,channel是可以有buffer大小的:make(chan int , 3).

select

这是channel的switch。

func main() {
  c1 := make(chan string)
  c2 := make(chan string)

  go func() {
    for {
      c1 <- "from 1"
      time.Sleep(time.Second * 2)
    }
  }()

  go func() {
    for {
      c2 <- "from 2"
      time.Sleep(time.Second * 3)
    }
  }()

  go func() {
    for {
      select {
      case msg1 := <- c1:
        fmt.Println(msg1)
      case msg2 := <- c2:
        fmt.Println(msg2)
      }
    }
  }()

  var input string
  fmt.Scanln(&input)
}