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



















