栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

《7天学会Go并发编程》第六天 go语言Sync.cond的应用和实现 go实现多线程联合执行

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《7天学会Go并发编程》第六天 go语言Sync.cond的应用和实现 go实现多线程联合执行

文章目录

目录

文章目录

前言

一、sync.Cond是什么

二、sync.Cond的使用

1. Sync.Cond初始化

2.Sync.Cond简单使用

3.Sync.Cond的BroadCast方法使用

4.Sync.Cond的Signal()方法使用

三、Cond的内部原理

总结



前言

前面的编程文章主要介绍了并发编程的一些原理和应用,主要解决了并发编程中的临界资源保护问题、多线程之间的通信问题、多线程执行顺序问题。但是在实际编程中,也会遇到一类常见问题就是多线程之间的条件执行。多线程之间的条件执行讲的是多个线程出于等待状态,接收到对应的信号后执行。举一个生活化的场景:很多人排队等公交车,每个人都做好了上车的准备,但是车还没有来。只能等,盼星星,盼月亮,公交车来了。公交车来了以后,对于排队候车的人来讲,会有两种情况:1、成功上车2、因为人太多,车辆拒载,没有排上座位。在这个例子当中,公交车上就是那个等待条件,并且发出接纳多少人上车的指令。

一、sync.Cond是什么

   sync.Cond位于sync.package的包中,主要功能是提供一个临时变量。通过这个临时变量实现了等待条件不满足时,线程阻塞、等待条件满足后,线程再执行的功能。 

二、sync.Cond的使用

1. Sync.Cond初始化

Cond初始化的过程中,需要传入一个Mutex类型的参数。

package main

import "sync"

func main() {
	mutex := sync.Mutex{}
	cond := sync.NewCond(&mutex)
}

 

2.Sync.Cond简单使用

下文实现一个简单的Cond使用,实现先开启一个go线程等待,线程阻塞等待至cond.BroadCast执行,实现对等待线程的唤醒。

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	signal := 1
	mutex := sync.Mutex{}
	cond := sync.NewCond(&mutex)
	go func() {
		cond.L.Lock()
		for signal == 1 {
			fmt.Println("线程开始等待")
			cond.Wait()
			fmt.Println("线程等待结束")
		}
		cond.L.Unlock()
	}()
	time.Sleep(200*time.Millisecond)
	cond.Broadcast()
	signal=0
	time.Sleep(200*time.Millisecond)

}

3.Sync.Cond的BroadCast方法使用

下文实现一个BroadCast应用,实现10个线程同时阻塞等待,条件变量执行BroadCase后,所有线程并发执行。因为使用的是BroadCast的方法,唤醒所有等待线程,所以使用waitGroup管理批量线程执行。

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	signal := 1
	mutex := sync.Mutex{}
	cond := sync.NewCond(&mutex)
	group := sync.WaitGroup{}
	group.Add(10)
	for i := 0; i < 10; i++ {
		go func(int1 int) {
			defer group.Done()
			cond.L.Lock()
			for signal == 1 {
				fmt.Printf("线程%d开始等待n",int1)
				cond.Wait()
				fmt.Printf("线程%d结束n",int1)
			}
			cond.L.Unlock()
		}(i)
	}
	time.Sleep(200*time.Millisecond)
	cond.Broadcast()
	signal=0
	group.Wait()
}

 对应的执行效果:

线程4开始等待
线程9开始等待
线程5开始等待
线程6开始等待
线程7开始等待
线程8开始等待
线程1开始等待
线程0开始等待
线程2开始等待
线程3开始等待
线程3结束
线程2结束
线程7结束
线程4结束
线程9结束
线程5结束
线程6结束
线程1结束
线程0结束
线程8结束

Process finished with the exit code 0
 

4.Sync.Cond的Signal()方法使用

下文实现一个BroadCast应用,实现10个线程同时阻塞等待,条件变量执行Signal后,所有线程并发抢占。因为使用的是Signal的方法,只会有一个线程会被执行。这个选择规则就是先到先得谁第一个等待,谁就第一个执行。

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	signal := 1
	mutex := sync.Mutex{}
	cond := sync.NewCond(&mutex)
	c := make(chan  struct{}, 1)
	for i := 0; i < 10; i++ {
		go func(int1 int) {
			defer func() {
				c<- struct{}{}
			}()
			cond.L.Lock()
			for signal == 1 {
				fmt.Printf("线程%d开始等待n",int1)
				cond.Wait()
				fmt.Printf("线程%d结束n",int1)
			}
			cond.L.Unlock()
		}(i)
	}
	time.Sleep(200*time.Millisecond)
	cond.Signal()
	signal=0
	<-c
}

对应的执行效果:

 线程0开始等待
线程9开始等待
线程2开始等待
线程3开始等待
线程4开始等待
线程5开始等待
线程6开始等待
线程7开始等待
线程8开始等待
线程1开始等待
线程0结束


三、Cond的内部原理

核心源码如下:

func (c *Cond) Wait() {
	c.checker.check()
	t := runtime_notifyListAdd(&c.notify)  //添加线程到等到等待队列
	c.L.Unlock()
	runtime_notifyListWait(&c.notify, t) //让等待队列的线程开始等待
	c.L.Lock()
}

总结

        以上就是今天要讲的内容,本文仅仅简单介绍了cond的使用,Cond提供了一种可以县实现多线程协同执行的机制。这种机制应用到了很多的工程中,后续会陆续更新一些相关的内容。

        欢迎各位大佬多提宝贵意见,多多留言互动~

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/989818.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号