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. ReactiveX 学习笔记(19)使用 RxSwift + RxCocoa 进行 GUI 编程

    课题 程序界面由3个文本编辑框和1个文本标签组成. 要求文本标签实时显示3个文本编辑框所输入的数字之和. 文本编辑框输入的不是合法数字时,将其值视为0. 3个文本编辑框的初值分别为1,2,3. 创建工 ...

  2. LeetCode OJ 60. Permutation Sequence

    题目 The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of th ...

  3. C#中让WebBrowser运行Javascript脚本

    C#中可以让Webbrowser运行Javascript脚本来实现各种自动化操作,比如点击网页上的按钮,输入用户名密码等等.代码也很简单: >>>>>>>&g ...

  4. ubuntu上装MySQL遇到的问题及解决办法

    验证原有主机上是否已安装mysql                运行sudo netstat -tap | grep mysql命令查看是否有Mysql的端口 查看到mysql已安装上了: 启动my ...

  5. 初始C语言中的数组(男神翁凯老师MOOC)

    定义数组 ●<类型>变量名称[元素数量]; ● int grades[100]; ●double weight[20]; ●元素数量必须是整数 ●C99之前:元素数量必须是编译时刻确定的字 ...

  6. JS-事件对象(鼠标键盘事件)

    一  事件对象 1 需要获取键盘和鼠标的信息的时候,用到事件对象.(e) 例如:document.onclick = function(e){ var  e = e || event;(做兼容) } ...

  7. 用PLSQL Developer 查看Oracle的存储过程

    1 2.输入 3.具体存储过程

  8. .net 中使用oracle 的sql 语句

    string sqlString = "Select * From emp  Where EMPNO=7369“; 一定不要写成 string sqlString = "Selec ...

  9. 第十章 优先级队列 (xa1)左式堆:结构

  10. 食物链(带权&种类并查集)

    食物链 http://poj.org/problem?id=1182 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9326 ...