博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go语言sync包的学习(Mutex、WaitGroup、Cond)
阅读量:7122 次
发布时间:2019-06-28

本文共 2274 字,大约阅读时间需要 7 分钟。

package main;import (	"fmt"	"sync"	"runtime"	"time")//加锁,注意锁要以指针的形式传进来,不然只是拷贝func total1(num *int, mu *sync.Mutex, ch chan bool) {	mu.Lock();	for i := 0; i < 1000; i++ {		*num += i;	}	ch <- true;	mu.Unlock();}//不加锁func total2(num *int, ch chan bool) {	for i := 0; i < 1000; i++ {		*num += i;	}	ch <- true;}//Lock、Unlock与RLock、RUnlock不能嵌套使用func total3(num *int, rwmu *sync.RWMutex, ch chan bool) {	for i := 0; i < 1000; i++ {		rwmu.Lock();		*num += i;		rwmu.Unlock();		if(i == 500) {			//读锁定			rwmu.RLock();			fmt.Print(*num, " ");			rwmu.RUnlock();		}	}	ch <- true;}func printNum(num int, cond *sync.Cond) {	cond.L.Lock();	if num < 5 {		//num小于5时,进入等待状态		cond.Wait();	}	//大于5的正常输出	fmt.Println(num);	cond.L.Unlock();}func main() {	//Once.Do()保证多次调用只执行一次	once := sync.Once{};	ch := make(chan bool, 3);	for i := 0; i < 3; i++ {		go func(n int) {			once.Do(func() {				//只会执行一次,因为闭包引用了变量n,最后的值为2				fmt.Println(n)			});			//给chan发送true,表示执行完成			ch <- true;		}(i);	}	for i := 0; i < 3; i++ {		//读取三次chan,如果上面三次没执行完会一直阻塞		<-ch;	}	//互斥锁,保证某一时刻只能有一个访问对象	mutex := sync.Mutex{};	ch2 := make(chan bool, 20);	//使用多核,不然下面的结果会一样	runtime.GOMAXPROCS(runtime.NumCPU());	num1 := 0;	num2 := 0;	for i := 0; i < 10; i++ {		go total1(&num1, &mutex, ch2);	}	for i := 0; i < 10; i++ {		go total2(&num2, ch2);	}	for i := 0; i < 20; i++ {		<-ch2;	}	//会发现num1与num2计算出的结果不一样	//而num1的结果才是正确的,因为total2没有加锁,导致多个goroutine操作num时发生数据混乱	fmt.Println(num1, num2);	//读写锁,多了读锁定,和读解锁,让多个goroutine同时读取对象	rwmutex := sync.RWMutex{};	ch3 := make(chan bool, 10);	num3 := 0;	for i := 0; i < 10; i++ {		go total3(&num3, &rwmutex, ch3);	}	for i := 0; i < 10; i++ {		<-ch3;	}	fmt.Println(num3);	//组等待,等待一组goroutine的结束	wg := sync.WaitGroup{};	//增加计数器	wg.Add(10);	for i:= 0; i< 10; i++ {		go func(n int) {			fmt.Print(n, " ");			//这里表示该goroutine执行完成			wg.Done();		}(i);	}	//等待所有线程执行完成	wg.Wait();	fmt.Println("");	//条件等待	mutex2 := sync.Mutex{};	//使用锁创建一个条件等待	cond := sync.NewCond(&mutex2);	for i := 0; i < 10; i++ {		go printNum(i, cond);	}	time.Sleep(time.Second * 1);	//等待一秒后,我们先唤醒一个等待,输出一个数字	cond.L.Lock()	cond.Signal();	cond.L.Unlock();	time.Sleep(time.Second * 1);	//再次待待一秒后,唤醒所有,输出余下四个数字	cond.L.Lock()	cond.Broadcast();	cond.L.Unlock();	time.Sleep(time.Second * 1);}

  

转载于:https://www.cnblogs.com/jkko123/p/6885389.html

你可能感兴趣的文章
SCVMM 2012 SP1 安装与配置指南(四)配置SMI-S提供程序来添加iSCSI存储
查看>>
Spring 的优秀工具类
查看>>
MySQL源码编译安装(CentOS-6.6+MySQL-5.6)
查看>>
CentOS 7 基于fastcgi 的lamp
查看>>
linux大神必备技能
查看>>
C语言:不使用(a+b)/2这种方式(会溢出),求两个数的平均值
查看>>
2.Python安装
查看>>
HttpUrlConnection Get 和Post请求
查看>>
split命令
查看>>
apache配置默认虚拟主机
查看>>
CSS3实现的图片加载动画效果
查看>>
Navitcat连接远程mysql服务器连不上
查看>>
绝对干货!史上最全自媒体人发文渠道汇总(小编亲测)
查看>>
安卓7.0正式版怎么刷?安卓7.0正式版刷机方法
查看>>
TransferQueue实例
查看>>
nginx的port_in_redirect配置
查看>>
网络协议分析
查看>>
堆排序算法
查看>>
dovecot主要配置文件
查看>>
理解Javascript--作用域和赋值操作
查看>>