zoukankan      html  css  js  c++  java
  • Go 协程(绿程/轻量级线程 用户态)--没有历史包袱

    协程

    初识

    GMP
    
    python 的单个协程占用 内存少
    
    import asyncio
    
    async def p(n : int) -> None:
        print(n)
        await asyncio.sleep(1)
    
    async def main():
        for i in range(1000):
            asyncio.create_task(p(i))
    
        await asyncio.sleep(30)
    
    if __name__ == '__main__':
        asyncio.run(main())
    
    
    
    go 的 协程 写起来简单
    
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    // Add 的数量与 Done 的数量必须相等
    
    func main(){
    	wg := sync.WaitGroup{}
    	for i:=0; i<100; i++{
    		wg.Add(1)
    		go func(i int){
    			defer wg.Done()
    			fmt.Printf("current i: %v 
    ", i)
    
    		}(i)
    	}
    	wg.Wait()
    }
    

    go 中的锁

    package main
    
    import "fmt"
    
    func add100(cnt *int) {
    	for i := 0; i < 100; i++ {
    		*cnt += 1
    	}
    }
    
    func sub100(cnt *int){
    	for i:= 0; i<100; i++{
    		*cnt -= 1
    	}
    }
    
    func main(){
    	// 因为是同步代码,所以此处不会造成最后数据不对,稍后我们改为协程
    	var cnt = 0
    	add100(&cnt)
    	// 此处加到 100 了
    	fmt.Println(cnt)
    	sub100(&cnt)
    	// 此处减到 0 了
    	fmt.Println(cnt)
    }
    
    ----========= 下面为协程代码, 因为出现共享数据 因为非原子性操作会造成数据不一致 ==========--------
    
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    func add100(cnt *int) {
    	defer wg.Done()
    	for i := 0; i < 100000; i++ {
    		*cnt += 1
    	}
    }
    
    func sub100(cnt *int){
    	defer wg.Done()
    	for i:= 0; i<100000; i++{
    		*cnt -= 1
    	}
    }
    var wg = sync.WaitGroup{}
    func main(){
    	wg.Add(2)
    	var cnt = 0
    	go add100(&cnt)
    	// 此处加到 100 了
    	fmt.Println(cnt)
    	go sub100(&cnt)
    	// 此处减到 0 了
    	wg.Wait()
    	fmt.Println(cnt)
    }
    
    
    ----======== 互斥锁 解决 数据同步问题 ============-------------
    
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    
    func add100(cnt *int) {
    	defer wg.Done()
    	for i := 0; i < 100000; i++ {
    		mutexLock.Lock()
    		*cnt += 1
    		mutexLock.Unlock()
    	}
    }
    
    func sub100(cnt *int){
    	defer wg.Done()
    	for i:= 0; i<100000; i++{
    		mutexLock.Lock()
    		*cnt -= 1
    		mutexLock.Unlock()
    	}
    }
    var wg = sync.WaitGroup{}
    var mutexLock = sync.Mutex{}
    func main(){
    	wg.Add(2)
    	var cnt = 0
    	go add100(&cnt)
    	// 此处加到 100 了
    	fmt.Println(cnt)
    	go sub100(&cnt)
    	// 此处减到 0 了
    	wg.Wait()
    	fmt.Println(cnt)
    }
    
    ---===== 一般绝大多数 web 系统都是 读多写少 =====--------
    // 读之间不产生影响, 写和读之间才会产生影响 ==》 读写锁
    
    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    var rwLock = sync.RWMutex{}
    // 绝大部分 web 系统属于 读多写少类型
    // 我们关注于 读 读 之间不产生影响, 只在 读写之间拥有 读写锁
    
    var wg = sync.WaitGroup{}
    
    func read(){
    	// 模拟读取数据
    	// 延迟注册一个 waitgroup 的 Done 方法
    	defer wg.Done()
    
    	// 此处我们加上 读写互斥锁 中的 读锁
    	rwLock.RLock()
    	fmt.Println("开始读取数据")
    	time.Sleep(time.Second) // 模拟 读取耗时 1 s
    	fmt.Println("完成读取数据")
    	// 释放 读锁
    	rwLock.RUnlock()
    }
    
    func write(){
    	// 模拟写操作
    	// 延迟注册一个 Done 方法
    	defer wg.Done()
    
    	// 添加写锁
    	rwLock.Lock()
    
    	// 模拟写操作耗时 10 s
    	fmt.Println("开始写入数据")
    	time.Sleep(time.Second * 10)
    	fmt.Println("完成写入数据")
    
    	// 释放写锁
    	rwLock.Unlock()
    
    }
    func main(){
    	var readCnt = 100
    	var writeCnt = 2
    
    	// 添加协程计数
    	wg.Add(readCnt + writeCnt)
    	// 模拟 100 次 读取操作
    	for i := 0; i<readCnt; i++{
    		go read()
    	}
    	// 模拟 2 次 写操作
    	for i := 0; i<writeCnt;i++{
    		go write()
    	}
    
    	// 等待所有协程完成
    	wg.Wait()
    
    }
    
    
    如果有来生,一个人去远行,看不同的风景,感受生命的活力。。。
  • 相关阅读:
    假期十一
    假期十
    假期九
    假期八
    假期七
    假期六
    假期五
    假期四
    2020.02.11
    2020.02.10
  • 原文地址:https://www.cnblogs.com/Frank99/p/15374294.html
Copyright © 2011-2022 走看看