GO基础Day11、简单并发

 一、协程
 goroutine 协程
 语法 go 函数 ,启动了一个子协程

 父协程退出,子协程马上停止

 1、简单粗暴 让父进程休眠时间,


var i = 0

func main() {
    
    //启动四个协程
    go XAdd()
	go XAdd()
    go XAdd()
    go XAdd()

    // 把这行注释后,i打印是0
	time.Sleep(time.Second * 3) // 简单粗暴休眠3秒

	fmt.Println(i)
}

func XAdd() { i++ } 


 2、使用协程计数器

 全局区域
 建立一个  var wg sync.WaitGroup

 父协程中
 设置等待3个子协程结束 wg.Add(3)
 等待数字变成0        wg.Wait()

 子协程中
 数字减去1添加  wg.Done()  



var wg sync.WaitGroup
var x = 0

func main() {

	wg.Add(3)

	go XAdd()
	go XAdd()
	go XAdd()

	wg.Wait()
	fmt.Println(x)  //打印的x不一定是15000

}


func XAdd() {
	for i := 0; i < 5000; i++ {
		x = x + 1
	}
	wg.Done()
}



 二、简单同步问题

 1、简短互斥锁

 在全局变量中
 sync.Mutex

 函数中
 Lock():加锁,其他无法使用
 Unlock():解锁,其他能使用



var wg sync.WaitGroup
var x = 0

func main() {

	wg.Add(3)
	go XAdd()
	go XAdd()
	go XAdd()

	wg.Wait()
	fmt.Println(x)  //打印的x不一定是15000

}

var loc sync.Mutex //锁

func XAdd() {
	for i := 0; i < 5000; i++ {
		loc.Lock()
		x = x + 1
		loc.Unlock()
	}
	wg.Done()
}






 2、读写锁

sync.RWMutex(读写互斥锁)
方法:
Lock():写锁,阻塞其他所有的读和写操作
Unlock():释放写锁。

RLock():读锁,允许多个 协程 同时持有读锁,但会阻塞写操作
RUnlock():释放读锁。

使用场景:适用于读操作频繁且写操作相对较少的场景


var wg sync.WaitGroup
var x = 0

func main() {

	wg.Add(5)
	go XAdd()
    go XAdd()
	go XRead()
	go XRead()
	go XRead()

	wg.Wait()
	fmt.Println(x) //打印的x不一定是15000

}

var loc sync.RWMutex //读写锁

func XAdd() {
	for i := 0; i < 5000; i++ {
		loc.Lock()
		x = x + 1
		loc.Unlock()
	}
	wg.Done()
}

func XRead() {
	for i := 0; i < 4; i++ {
		loc.RLock()
		fmt.Println(x)
		loc.RUnlock()
	}
	wg.Done()
}





 3.原子操作(atomic包)


var wg sync.WaitGroup
var x int64 = 0

func main() {

	wg.Add(3)

	go XAdd()
	go XAdd()
	go XAdd()

	wg.Wait()
	fmt.Println(x)
}

func XAdd() {
	for i := 0; i < 200000; i++ {
		atomic.AddInt64(&x, 1)  // 这里使用原子操作
	}
	wg.Done()
}


 二、协程通信
 chan通道,是队列

var wg sync.WaitGroup        //是父进程等待子进程

func main() {


    wg.Add(1)

	// var ch1 chan int     //   是引用类型 是个nil
	ch := make(chan int)  // 开通一个 无缓冲,的通道

	go fu(ch)            //要这个通道和子协程链接
	ch <- 999            //才能向通道输入内容

    hh :=  <-ch
    fmt.Println(hh," am  ii ")
    

	wg.Wait()

}


func fu(ch chan int) {

	ii := <-ch                // 等待接受内容
	fmt.Println(ii, " am  ii ")
    ch <- 66

    close(ch)             //用完了,记得关闭

    wg.Done()

}


 函数的参数中
  chan<- 只能写
  <-chan 只能读

func fu(ch chan int)  // 可以写和读
func fu(ch <-chan int)  //只能读
func fu(ch chan<- int)  //只能写



有缓冲,的通道,容量为 1 
ch := make(chan int, 1) 

是一个队列,
队列满了,就不能写入
队列空,就不能读取


读取时
i, ok := <-ch 
// ok是false,说明已经没有啦

// 会读取,不是副本的遍历
for i := range ch { 
    fmt.Println(i)
}


len(ch) 求已经存多少
cap(ch) 求容量大小


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值