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. DO and DOES Reduction

    DO and DOES Reduction Share Tweet Share Tagged With: DO and DOES Reductions ‘Do’ and ‘does’ can be r ...

  2. Kubernetes 1.8.x 全手动安装教程----转自Kubernetes中文社区(部分内容根据实验环境做了些修改,特此感谢Kubernetes中文社区)

    Kubernetes 提供了许多云端平台与操作系统的安装方式,本章将以全手动安装方式来部署,主要是学习与了解 Kubernetes 创建流程.若想要了解更多平台的部署可以参考 Picking the ...

  3. webpack异步加载业务模块

    虽然把我们用到的JS文件全部打包一个可以节省请求数,但如果打包后的JS文件过大,那么也容易出现白屏现象,许多操作失灵.而且一些区域是点到才出现,那么相关的JS其实可以剥离出这个大JS文件外.这就涉及到 ...

  4. sql help cs

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Confi ...

  5. 18.2 不同用户 不同颜色光标 redis

    上次,我们完成了 change 这个event 通过 collaborationsrvice 与 server 进行 sockrt io 将 client端的监听的 change 发给 server ...

  6. 吴裕雄 20-MySQL NULL 值处理

    MySQL NULL 值处理我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作.为了 ...

  7. Java happen-before

    下面是happens-before原则规则: 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作: 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作 ...

  8. laravel 命令行创建controller 创建数据库表迁移 创建module

    1.php artisan 查看命令列表 2.php artisan make:controller ArticleController 命令 创建控制器 3.创建数据库迁移表 创建文章表 php a ...

  9. shell重定向命令执行顺序

    重定向内容介绍 一条shell命令的执行包含三个文件描述符:标准输入(键盘等) stdin 0,标准正确输出(屏幕等) stdout 1,标准错误输出(屏幕等)stderr 2   通过重定向可以指定 ...

  10. nutch笔记

    1.Nutch 是一个开源Java实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫.