Go语言使用go
关键词实现goroutine并发,可以通过channel
传输数据。
go关键词修饰函数实现goroutine并发:
func main_go() {
// runtime.GOMAXPROCS(最大256)
fmt.Println(runtime.NumCPU()) // 16
runtime.GOMAXPROCS(8) // 8核16线程,默认就是runtime.NumCPU()
var w sync.WaitGroup // 跟java的countdown差不多
w.Add(10)
for i := 0; i < 10; i++ {
// w.Add(1)
// 使用go,相当于new Thread().start() . 栈:2K
go func(i int) {
defer w.Done()
fmt.Printf("goooooo:::%d
", i)
}(i)
}
fmt.Println("demo2")
w.Wait()
// time.Sleep(time.Second)
// `GMP` m:n 把m个G交给n个操作系统线程执行
}
channel变量实现数据交换:
func main_channel() {
// channel FIFO
// var a []int
// var b chan int
var w sync.WaitGroup
w.Add(1)
var c = make(chan int /*, 1*/) // 初始化通道,通道必须初始化才能使用
go func() {
x := <-c
// <- c // 可以直接忽略
fmt.Printf("x=%d
", x)
w.Done()
}()
c <- 10
fmt.Println(c)
// 关闭通道
close(c)
w.Wait()
// <- 不管是发送还是接受,都使用这个符号
// 发送:c <- 1
// 接受:x := <- c
// 关闭close()
// 单向通道
var get_channel <-chan int // 只能取
var put_channel chan<- int // 只能存
get_channel = make(<-chan int)
put_channel = make(chan<- int)
fmt.Println(get_channel, put_channel)
}
使用select实现多路复用:
func main_select() {
ch := make(chan int, 2)
for i := 0; i < 10; i++ {
select {
case x := <-ch:
fmt.Println(x)
case ch <- i:
}
}
}
互斥锁:
func main_lock() {
var w sync.WaitGroup
w.Add(2)
// 互斥锁
var lock sync.Mutex
var x = 0
incr := func() {
for i := 0; i < 50000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
w.Done()
}
go incr()
go incr()
w.Wait()
fmt.Printf("x=%d
", x)
}
读写锁:
func main_rwlock() {
var w sync.WaitGroup
w.Add(600)
// 读写锁
var lock sync.RWMutex
var x = 0
read := func() {
lock.RLock() // reading lock
fmt.Printf("x=%d
", x)
time.Sleep(time.Millisecond)
w.Done()
lock.RUnlock() // reading unlock
}
write := func() {
lock.Lock() // writing lock
x += 1
time.Sleep(25 * time.Millisecond)
w.Done()
lock.Unlock() // writing unlock
}
for i := 0; i < 100; i++ {
go write()
}
time.Sleep(50 * time.Millisecond)
for i := 0; i < 500; i++ {
go read()
}
w.Wait()
}