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);
}

  

go语言sync包的学习(Mutex、WaitGroup、Cond)的更多相关文章

  1. go语言time包的学习(Time,Location,Duration,Timer,Ticker)

    package main;   import (     "time"     "fmt" )   func main() {     //time.Time代 ...

  2. go语言log包的学习(log,Logger)

    package main; import ( "log" "os" "time" "fmt" ) func main() ...

  3. go语言path包和filepath包的学习与使用

    path包的使用 package main; import ( "fmt" "path" ) //go语言path包的学习 func main() { //返回 ...

  4. R语言 ggplot2包

    R语言  ggplot2包的学习   分析数据要做的第一件事情,就是观察它.对于每个变量,哪些值是最常见的?值域是大是小?是否有异常观测? ggplot2图形之基本语法: ggplot2的核心理念是将 ...

  5. Go中sync包学习

    前面刚讲到goroutine和channel,通过goroutine启动一个协程,通过channel的方式在多个goroutine中传递消息来保证并发安全.今天我们来学习sync包,这个包是Go提供的 ...

  6. golang 中 sync包的 WaitGroup

    golang 中的 sync 包有一个很有用的功能,就是 WaitGroup 先说说 WaitGroup 的用途:它能够一直等到所有的 goroutine 执行完成,并且阻塞主线程的执行,直到所有的 ...

  7. 从实例学习 Go 语言、"并发内容" 学习笔记及心得体会、Go指南

    第一轮学习 golang "并发内容" 学习笔记,Go指南练习题目解析.使用学习资料 <Go-zh/tour tour>.记录我认为会比较容易忘记的知识点,进行补充,整 ...

  8. Sync包

    sync同步包 Mutex互斥锁: 能够保证在同一时间段内仅有一个goroutine持有锁,有且仅有一个goroutine访问共享资源,其他申请锁的goroutine将会被阻塞直到锁被释放.然后重新争 ...

  9. go语言中sync包和channel机制

    文章转载至:https://www.bytelang.com/article/content/A4jMIFmobcA= golang中实现并发非常简单,只需在需要并发的函数前面添加关键字"Go&quo ...

随机推荐

  1. android Button、TabLayout英文自动改小写为大写的问题

    如果是Button自动大写问题,直接设置Button的 textAllCaps="false" 即可: 如果是TabLayout出现全大写问题,先在style.xml加入属性: & ...

  2. Uni2D入门

    转载 http://blog.csdn.net/kakashi8841/article/details/17558059 开始 Uni2D增加了一些新的便利的特性给Unity,它们用于推动你2D工作流 ...

  3. 学习JS的心路历程-参数传递方式(上)

    很多人认为JS的传递方式是值是Call by value, 物件及数组是Call by Reference.甚至还有人宣称其实JS是Call by sharing,那到底是哪一个呢? 这两天我们一一来 ...

  4. js基础-函数基础

    js 先对函数进行解析 然后在执行函数 定义一个函数 实现求两个数的乘 function mult(a,b){ return a*b; } mult(1,3) 计算1 - n 的和 封装成函数 fun ...

  5. Numpy知识(三)

    ndarray的花式索引. 正负数索引,正数就是从0开始的下标正向寻找,负数是-1开始的负向寻找. arr[[1,5,2,6],[0,3,1,2]]:拿取arr[1,0],arr[5,3],arr[2 ...

  6. jekins的一些配置

    GotPC_Excel_Branches丢弃旧的构建 svn http://devsvn.uuzuonline.com/GOT_PC_PRIVATE/config/trunk构建Execute she ...

  7. div下面多个a标签的点击事件,并且获取a的属性

    $('.fensiselect').on('click','a',function(){ var id= $(this).attr('fanid'); alert(id) })

  8. IDEA配置 gradle

    下载解压自己需要的gradle版本:https://gradle.org/releases/(免安装)  配置环境变量 打开命令窗口,输入 gradle -v IDEA配置gradle:file-&g ...

  9. intellij idea 搜索功能快捷键

    intellij idea是一款超智能的编译器,因此在信息资源的搜索功能中给我们的用户提供了很大的帮助.同样作为java编译器的eclipse和myeclipse在搜索方面就比intellij ide ...

  10. 游戏AI技术

    [Unity3D人工智能编程精粹] 1.运动层.决策层.战略层. 运动层.决策层包含的算法是针对单个角色的,战略层是针对小队乃至更大规模群体的. 导航和寻路是运行层的主要任务. 决策层决定角色下一时间 ...