1.go test() 主死随从
package mainimport ("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.WaitGroupfunc 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 mainimport ("fmt""sync"
)var wg sync.WaitGroup
var totalNum int// 增加锁机制
var lock sync.Mutexfunc 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 mainimport ("fmt""sync"
)var wg sync.WaitGroup
var totalNum int// 增加锁机制
var lock sync.Mutexfunc add() {defer wg.Done()for i := 0; i < 10000; i++ {lock.Lock()totalNum = totalNum + 1lock.Unlock()}
}
func sub() {defer wg.Done()for i := 0; i < 10000; i++ {lock.Lock()totalNum = totalNum - 1lock.Unlock()}
}func main() {//开启协程wg.Add(2)go add()go sub()//阻塞主线程wg.Wait()//time.Sleep(time.Second)fmt.Println(totalNum)}
6.读写锁(读多写少)sync.RWMutex
package mainimport ("fmt""sync""time"
)var wg sync.WaitGroup
var totalNum int// 增加锁机制
var lock sync.RWMutexfunc 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 intintChan = make(chan int, 3)fmt.Println("管道的引用类型 ", intChan)//先管道存储数据intChan <- 10num := 20intChan <- num//从管道存储数据num1 := <-intChanfmt.Println(num1)num2 := <-intChanfmt.Println(num2)fmt.Println("管道的长度 ", len(intChan), "管道的容量", cap(intChan))}
8.管道关闭 不能写可以读
package mainimport "fmt"func main() {//定义一个管道var intChan chan intintChan = make(chan int, 3)fmt.Println("管道的引用类型 ", intChan)//先管道存储数据intChan <- 10num := 20intChan <- num//从管道存储数据num1 := <-intChanfmt.Println(num1)num2 := <-intChanfmt.Println(num2)//关闭管道close(intChan)//管道关闭 不能写可以读fmt.Println("管道的长度 ", len(intChan), "管道的容量", cap(intChan))}
9.管道的遍历 用for-range
遍历前需要关闭管道
package mainimport "fmt"func main() {//定义一个管道var intChan chan intintChan = 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.WaitGroupfunc writeDta(intChan chan int) {defer wg.Done()for i := 0; i <= 50; i++ {intChan <- ifmt.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 mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc main() {//读和写的协程通常操作一个管道//默认读写管道//inChan := make(chan int, 50)//声明一个只写的管道var intChanw chan<- intintChanw = make(chan<- int, 3)intChanw <- 20fmt.Println("intChan2 ", intChanw)//读管道var intChanR <-chan intif intChanR != nil {num1 := <-intChanRfmt.Println("read ", num1)}}
11.管道的阻塞
当管道只写入数据,没有读取,就会出现阻寒:
12