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. node-sass:npm install node-sass --save

    从git上拉下来的项目,要先安装依赖, 再运行. 缺少node-sass:npm install node-sass --save

  2. 【原】Ubuntu virtual terminal

    CTRL+ALT+F1 ~ F6 six virtual terminal ALT-F7 return to graphic desktop

  3. 0.1Linux系统开发Angular项目一一首次运行环境的安装(chrome ,terminator,git,node)

    首先,保证你已经安装了虚拟机(虚拟机可以用virturalbox或者VM)并安装了ubuntu镜像! 安装Chrome浏览器 安装terminator(可以多开)代替原来的命令行工具 sudo apt ...

  4. c# vs2013部署项目

    http://demo.netfoucs.com/shinepan/article/details/24865931

  5. 关于在VS2008和VS2010中禁用及卸载Visual Assist X的方法研究——转载

    禁用和启用   此方法对于VS2008和VS2010 都适用. 在VS2008或VS2010菜单栏中选择“VassistX”选项卡,找到“Enable/Disable Visual Assist X” ...

  6. unity3d API知识点随记

    1.transform.translate是增加transform面板相应的数值x,y,z是以本地坐标系为方向:transform.transformdirection是以世界坐标系为方向,可以去测试 ...

  7. pl2303 驱动

    https://blog.csdn.net/ouening/article/details/70947759

  8. 04_web基础(六)之请求转发与重定向

    1.交互方式 Web组件之间跳转: 从AServlet 跳转到 BServlet. 三种类型: 1:请求转发(forward) 2:URL重定向(redirect) 3:请求包含(include) 3 ...

  9. java.security.MessageDigest (1)

    我们知道,编程中数据的传输,保存,为了考虑安全性的问题,需要将数据进行加密.我们拿数据库做例子.如果一个用户注册系统的数据库,没有对用户的信息进行保存,如,我去页面注册,输入"Vicky&q ...

  10. JMeter学习(三)元件的作用域与执行顺序(转载)

    转载自 http://www.cnblogs.com/yangxia-test 1.元件的作用域 JMeter中共有8类可被执行的元件(测试计划与线程组不属于元件),这些元件中,取样器是典型的不与其它 ...