1.go test() 主死随从
package main
import (
"fmt"
"strconv"
"time"
)
func test() {
for i := 1; i <= 10; i++ {
fmt.Println("hello " + strconv.Itoa(i))
//阻塞
time.Sleep(time.Second)
}
}
func main() {
//开启协程
go test()
for i := 1; i <= 10; i++ {
fmt.Println(" main msg " + strconv.Itoa(i))
//阻塞
time.Sleep(time.Second)
}
}
2.共享i 读写混乱
func test() {
for i := 1; i <= 10; i++ {
fmt.Println("hello " + strconv.Itoa(i))
//阻塞
time.Sleep(time.Second)
}
}
func main() {
//开启协程
for i := 0; i < 4; i++ {
//共享i 读写混乱
/*go func() {
fmt.Println("hello ", strconv.Itoa(i))
}()*/
//匿名 +闭包 ==解决共享i 混乱的问题
go func(n int) {
fmt.Println("hello ", strconv.Itoa(n))
}(i)
}
time.Sleep(time.Second)
}
3.协程执行完退出WaitGroup
var wg sync.WaitGroup
func main() {
//开启协程
for i := 0; i < 5; i++ {
//共享i 读写混乱
/*go func() {
fmt.Println("hello ", strconv.Itoa(i))
}()*/
wg.Add(1)
//匿名 +闭包 ==解决共享i 混乱的问题
go func(n int) {
fmt.Println("hello ", strconv.Itoa(n))
wg.Done()
}(i)
}
//阻塞主线程
wg.Wait()
//time.Sleep(time.Second)
}
4.加减操作造成数据混乱
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var totalNum int
// 增加锁机制
var lock sync.Mutex
func add() {
defer wg.Done()
for i := 0; i < 10000; i++ {
//lock.Lock()
totalNum = totalNum + 1
//lock.Unlock()
}
}
func sub() {
defer wg.Done()
for i := 0; i < 10000; i++ {
//lock.Lock()
totalNum = totalNum - 1
//lock.Unlock()
}
}
func main() {
//开启协程
wg.Add(2)
go add()
go sub()
//阻塞主线程
wg.Wait()
//time.Sleep(time.Second)
fmt.Println(totalNum)
}
5.增加锁机制sync.Mutex互斥锁
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var totalNum int
// 增加锁机制
var lock sync.Mutex
func add() {
defer wg.Done()
for i := 0; i < 10000; i++ {
lock.Lock()
totalNum = totalNum + 1
lock.Unlock()
}
}
func sub() {
defer wg.Done()
for i := 0; i < 10000; i++ {
lock.Lock()
totalNum = totalNum - 1
lock.Unlock()
}
}
func main() {
//开启协程
wg.Add(2)
go add()
go sub()
//阻塞主线程
wg.Wait()
//time.Sleep(time.Second)
fmt.Println(totalNum)
}
6.读写锁(读多写少)sync.RWMutex
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var totalNum int
// 增加锁机制
var lock sync.RWMutex
func read() {
defer wg.Done()
lock.RLock()
fmt.Println("读数据")
time.Sleep(time.Second)
lock.RUnlock()
}
func write() {
defer wg.Done()
lock.Lock()
fmt.Println("写数据")
time.Sleep(time.Second * 10)
lock.Unlock()
}
func main() {
//开启协程
wg.Add(6)
for i := 0; i < 5; i++ {
go read()
}
go write()
//阻塞主线程
wg.Wait()
//time.Sleep(time.Second)
fmt.Println(totalNum)
}
7.管道
func main() {
//定义一个管道
var intChan chan int
intChan = make(chan int, 3)
fmt.Println("管道的引用类型 ", intChan)
//先管道存储数据
intChan <- 10
num := 20
intChan <- num
//从管道存储数据
num1 := <-intChan
fmt.Println(num1)
num2 := <-intChan
fmt.Println(num2)
fmt.Println("管道的长度 ", len(intChan), "管道的容量", cap(intChan))
}
8.管道关闭 不能写可以读
package main
import "fmt"
func main() {
//定义一个管道
var intChan chan int
intChan = make(chan int, 3)
fmt.Println("管道的引用类型 ", intChan)
//先管道存储数据
intChan <- 10
num := 20
intChan <- num
//从管道存储数据
num1 := <-intChan
fmt.Println(num1)
num2 := <-intChan
fmt.Println(num2)
//关闭管道
close(intChan)
//管道关闭 不能写可以读
fmt.Println("管道的长度 ", len(intChan), "管道的容量", cap(intChan))
}
9.管道的遍历 用for-range
遍历前需要关闭管道
package main
import "fmt"
func main() {
//定义一个管道
var intChan chan int
intChan = make(chan int, 100)
fmt.Println("管道的引用类型 ", intChan)
//先管道存储数据
for i := 0; i < 99; i++ {
intChan <- i
}
//关闭管道 遍历前需要关闭管道
close(intChan)
//从管道存储数据
for v := range intChan {
fmt.Println("value =", v)
}
//管道关闭 不能写可以读
fmt.Println("管道的长度 ", len(intChan), "管道的容量", cap(intChan))
}
10.读和写的协程通常操作一个管道
var wg sync.WaitGroup
func writeDta(intChan chan int) {
defer wg.Done()
for i := 0; i <= 50; i++ {
intChan <- i
fmt.Println("写", i)
time.Sleep(time.Second)
}
close(intChan)
}
func read(intChan chan int) {
defer wg.Done()
for v := range intChan {
fmt.Println("read ", v)
time.Sleep(time.Second)
}
}
func main() {
//读和写的协程通常操作一个管道
inChan := make(chan int, 50)
wg.Add(2)
go writeDta(inChan)
go read(inChan)
wg.Wait()
}
11.读写管道
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
//读和写的协程通常操作一个管道
//默认读写管道
//inChan := make(chan int, 50)
//声明一个只写的管道
var intChanw chan<- int
intChanw = make(chan<- int, 3)
intChanw <- 20
fmt.Println("intChan2 ", intChanw)
//读管道
var intChanR <-chan int
if intChanR != nil {
num1 := <-intChanR
fmt.Println("read ", num1)
}
}
11.管道的阻塞
当管道只写入数据,没有读取,就会出现阻寒:
12