chap04 并发编程
1.Go语言支持语言级别轻量级别线程,称之为goroutine,由Go语言运行时runtime管理。如下多线程实例:
package main
import (
"fmt";
"sync";
"runtime"
)
var counter int = 0
func Count(lock *sync.Mutex){
lock.Lock()
counter++
fmt.Println(counter)
lock.Unlock()
}
func main(){
lock:=&sync.Mutex{}
for i:=0;i<10;i++ {
go Count(lock)
}
for {
lock.Lock()
c:=counter
lock.Unlock()
runtime.Gosched() //用于让cpu让出时间片
if c>=10 {
break
}
}
}
2.Go语言共享数据理念:不要通过共享内存来通信,而应该通过通信来共享内存。
3.channel是go语言goroutine间的通信方式。可以使用channel在不同的goroutine线程之间传递消息。channel是类型相关的。
定义:var chanName chan type ,初始化:chanName := make(chan type)。
写入:chanName <- value,读取:value := <- chanName。读取都会导致程序阻塞等待。
package main
import "fmt"
import "time"
func Count(ch chan int){
ch <- 1
fmt.Println(time.Now().UnixNano())
}
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) {
<-ch
fmt.Println("--------")
}
}
输出:
1470927062503429479
--------
4.select用于处理异步io,类似于switch,但是case的条件必须是io操作,没有判断条件。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
package main
import "fmt"
func main(){
ch := make(chan int,1)
for {
select {
case ch <- 0:
case ch <- 1:
}
i:=<-ch
fmt.Println("Value received",i)
}
}
需要确保执行时有一个case可以执行,否则死锁:fatal error: all goroutines are asleep - deadlock!
package main
import "fmt"
func main(){
ch := make(chan int,1)
for {
select {
case <-ch :
}
fmt.Println("Value received")
}
}
5.缓冲机制:设置缓冲区,缓冲区写满后才阻塞写。ch:=make(chan int,1024)
6.利用channel处理超时:
package main
import "fmt"
import "time"
func main(){
timeout := make(chan bool,1)
go func(){
time.Sleep(time.Second)
timeout<-true
}()
var ch chan int
select {
case <- ch :
case <- timeout:
fmt.Println("TimeOut...")
}
}
7.单项channel:
正常:var ch chan int
单项写:var ch chan<- int
单项读:var ch <-chan int
8.runtime.GOMAXPROCS(N)设置N个cpu参与到运算。runtime.Sched()释放时间片。
9.同步锁:syncMutex。读写锁:sync.RWMutex。
10.全局唯一操作:sync.Once
package main
import "fmt"
import "sync"
var once sync.Once
func hi() {
fmt.Print("hi")
}
func main(){
for i:=0;i<10;i++ {
fmt.Println("Round",i)
once.Do(hi)
}
}
1.Go语言支持语言级别轻量级别线程,称之为goroutine,由Go语言运行时runtime管理。如下多线程实例:
package main
import (
"fmt";
"sync";
"runtime"
)
var counter int = 0
func Count(lock *sync.Mutex){
lock.Lock()
counter++
fmt.Println(counter)
lock.Unlock()
}
func main(){
lock:=&sync.Mutex{}
for i:=0;i<10;i++ {
go Count(lock)
}
for {
lock.Lock()
c:=counter
lock.Unlock()
runtime.Gosched() //用于让cpu让出时间片
if c>=10 {
break
}
}
}
2.Go语言共享数据理念:不要通过共享内存来通信,而应该通过通信来共享内存。
3.channel是go语言goroutine间的通信方式。可以使用channel在不同的goroutine线程之间传递消息。channel是类型相关的。
定义:var chanName chan type ,初始化:chanName := make(chan type)。
写入:chanName <- value,读取:value := <- chanName。读取都会导致程序阻塞等待。
package main
import "fmt"
import "time"
func Count(ch chan int){
ch <- 1
fmt.Println(time.Now().UnixNano())
}
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) {
<-ch
fmt.Println("--------")
}
}
输出:
1470927062503429479
--------
4.select用于处理异步io,类似于switch,但是case的条件必须是io操作,没有判断条件。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
package main
import "fmt"
func main(){
ch := make(chan int,1)
for {
select {
case ch <- 0:
case ch <- 1:
}
i:=<-ch
fmt.Println("Value received",i)
}
}
需要确保执行时有一个case可以执行,否则死锁:fatal error: all goroutines are asleep - deadlock!
package main
import "fmt"
func main(){
ch := make(chan int,1)
for {
select {
case <-ch :
}
fmt.Println("Value received")
}
}
5.缓冲机制:设置缓冲区,缓冲区写满后才阻塞写。ch:=make(chan int,1024)
6.利用channel处理超时:
package main
import "fmt"
import "time"
func main(){
timeout := make(chan bool,1)
go func(){
time.Sleep(time.Second)
timeout<-true
}()
var ch chan int
select {
case <- ch :
case <- timeout:
fmt.Println("TimeOut...")
}
}
7.单项channel:
正常:var ch chan int
单项写:var ch chan<- int
单项读:var ch <-chan int
8.runtime.GOMAXPROCS(N)设置N个cpu参与到运算。runtime.Sched()释放时间片。
9.同步锁:syncMutex。读写锁:sync.RWMutex。
10.全局唯一操作:sync.Once
package main
import "fmt"
import "sync"
var once sync.Once
func hi() {
fmt.Print("hi")
}
func main(){
for i:=0;i<10;i++ {
fmt.Println("Round",i)
once.Do(hi)
}
}
有疑问加站长微信联系(非本文作者)