golang 并发

1. 延时与并发

本节,讨论延时和并发的关系。以下都以cpu资源足够的情况下讨论

假如一个接口,延时为x ms ,则一个并发,每秒可处理 k=100/x

如果需要处理m qps,则需要至少 m/k 个goroutine

事与愿违,当并发提高后,可能后面响应可能就增大,导致每秒处理量小于k

这个时候,整个系统就触摸到天花板了。

这个时候,增加并发,并不能解决问题,而是需要优化响应时间了。

2. 哲学家问题 的一种csp 解法

基本思路: 首先A为左边,B为右边 1. 哲学家会等待并锁定A边的叉 2. 如果B边没人用,则锁定B边 然后拿起两根叉,吃面 3. 如果B边被锁定,则解锁A边,A和B 交换,重复执行第一步骤

golang 代码实现可参考:

package main

import (
	"fmt"
	"time"
)

type gopher struct {
	id    int
	count int
}

func (g *gopher) eat() {
	fmt.Printf("%d eat\n", g.id)
	g.count++
	time.Sleep(time.Second / 10)
}

func (g *gopher) think() {}

type folk struct {
	id        int
	available chan bool
}

var folks [5]folk

func (f *folk) lock() {
	f.available <- true
}
func (f *folk) unlock() {
	<-f.available
}
func (f *folk) trylock() bool {
	select {
	case f.available <- true:
		return true
	default:
		return false
	}
}
func (g *gopher) left() int {
	return g.id
}
func (g *gopher) right() int {
	return (g.id + 1) % len(folks)
}

func (g *gopher) get_folks() {
	need := []*folk{
		&folks[g.left()],
		&folks[g.right()],
	}
	fmt.Printf("%d need folk %d %d\n", g.id, g.left(), g.right())
	first := 0
	for {
		second := (first + 1) % len(need)
		fmt.Printf("%d get folk %d\n", g.id, need[first].id)
		//等待并取得一个叉
		need[first].lock()
		// 如果第二个叉没人用,则取,否则将之前取的叉放回去
		if need[second].trylock() {
			fmt.Printf("%d get folk %d\n", g.id, need[second].id)
			return
		}
		fmt.Printf("%d giveup folk %d\n", g.id, need[first].id)
		need[first].unlock()
		//盯着别人手里的叉
		first = second
	}
}

func (g *gopher) put_folks() {
	fmt.Printf("%d put folk %d %d\n", g.id, g.left(), g.right())
	folks[g.left()].unlock()
	folks[g.right()].unlock()
}

func (g *gopher) dine() {
	fmt.Printf("%d start\n", g.id)
	for {
		g.think()
		g.get_folks()
		g.eat()
		g.put_folks()
	}
}

func main() {
	gs := []*gopher{}
	for i := 0; i < 5; i++ {
		folks[i].available = make(chan bool, 1)
		folks[i].id = i
		g := &gopher{id: i}
		gs = append(gs, g)
		go g.dine()
	}
	time.Sleep(10 * time.Second)
	fmt.Printf("done\n")
	for i := 0; i < 5; i++ {
		fmt.Printf("%d eat count %d\n", gs[i].id, gs[i].count)
	}
}
humboldt Written by:

humboldt 的趣味程序园