竞争无处不在,青春永不言败!专业撸代码,副业修bug

Talk is cheap , show me the code!



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 \n", 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()

}

posted @ 2021-10-06 21:30  云雾散人  阅读(63)  评论(0编辑  收藏  举报

Your attitude not your aptitude will determine your altitude!

如果有来生,一个人去远行,看不同的风景,感受生命的活力!