自信人生二百年,会当击水三千里
随着阅历的增长,发现有的时候个人命运的改变,很大程度上不仅取决于历史的进程,还有的的时候还取决于个人的雄心壮志。自信人生二百年,会当击水三千里。伟人之所以称之为伟人,不仅在于历史功绩的卓越,还在于敢叫日月换新天的非凡勇气。现实生活中无数的人总是口头叫喊着改变命运。可实际上有多少人会付出实践。就拿工作这件事情来讲吧,无论老板的要求的工作强度是否合理,只要钱给够,绝大部分的打工人还是会选择默默的顺从,即便有的时候不给加班费用,只要不是压榨的特别的厉害,绝大部分的人还是选择忍一忍,却从来不思考背后的逻辑。老板之所以为老板,不但是因为拥有资本,更重要的是对某一个行业的规则早已经通透,无论是投标时的翻云腹地,还是利益的划定分配,没有日积月累的堆积是不可能完成工打工者到老板的身份转变的。与其抱怨,不如行动,2021年的今天,没有一个人是生活的傻子。
缓冲信道和工作池
1、什么是缓冲信道(BufferChannel)?
缓冲信道本质是一个具有指定容量的信道,只在缓冲已满的情况,才会阻塞向缓冲信道(Buffered Channel)发送数据。同样,只有在缓冲为空的时候,才会阻塞从缓冲信道接收数据。
//举个栗子
func main() {
//下面的案例中创建了一个容量为3的信道,可以保存三个字符串
ch := make(chan string, 3)
ch <- "naveen"
ch <- "paul"
fmt.Println("capacity is", cap(ch))
fmt.Println("length is", len(ch))
fmt.Println("read value", <-ch)
fmt.Println("new length is", len(ch))
}
2、什么是工作池(WaitGroup)?
工作池用于等待一批 Go 协程执行结束,程序控制会一直阻塞,直到这些协程全部执行完毕。
//举个栗子
func process(i int, wg *sync.WaitGroup) {
fmt.Println("started Goroutine ", i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n", i)
wg.Done()
}
func main() {
no := 3
var wg sync.WaitGroup
for i := 0; i < no; i++ {
wg.Add(1)
go process(i, &wg)
}
wg.Wait()
fmt.Println("All go routines finished executing")
}
Select
1、什么是Select?
select 用于在多个发送和接收信道中进行选择,在程序运行的过程中,select会一直阻塞,直到发送/接收操作准备就绪,如果有多个信道操作准备完毕,select会随机的选取其中之一执行,语法作用与switch相似,但是不同的是select作用于信道操作。
//举个栗子
func server1(ch chan string) {
time.Sleep(6 * time.Second)
ch <- "from server1"
}
func server2(ch chan string) {
time.Sleep(3 * time.Second)
ch <- "from server2"
}
func main() {
output1 := make(chan string)
output2 := make(chan string)
go server1(output1)
go server2(output2)
select {
case s1 := <-output1:
fmt.Println(s1)
case s2 := <-output2:
fmt.Println(s2)
}
}
2、死锁存在的情况
信道如果没有接收到数据,导致select语句一直阻塞,最后导致死锁
//举个栗子
func main() {
ch := make(chan string)
select {
case <-ch:
}
}
避免死锁的方式
func main() {
ch := make(chan string)
select {
case <-ch:
default:
fmt.Println("default case executed")
}
Mutex
1、什么是Mutex?
Mutex是一种加锁的机制,可以确保在某一个时刻限制只有一个协程能访问临界区的资源,防止出现竞态条件。
//举个栗子
var x = 0
func increment(wg *sync.WaitGroup, m *sync.Mutex) {
m.Lock()
x = x + 1
m.Unlock()
wg.Done()
}
func main() {
var w sync.WaitGroup
var m sync.Mutex
for i := 0; i < 1000; i++ {
w.Add(1)
go increment(&w, &m)
}
w.Wait()
fmt.Println("final value of x", x)
}
总结
上面的关于缓冲信道、工作池、select、Mutex的相关知识是非常重要的,这个部分的内容对于掌握多个协程并发的场景非常的重要,特别是在一些高并发的场景中非常的适用,因此建议必须拿下这个部分的内容。