package main

import (
"fmt"
"sync"
"time"
) /*
mt.Lock()
抢锁
一次只能被一个协程锁住
其余想要抢到这把锁的协程阻塞等待至前面的协程将锁释放
mt.Lock()的可能性有两种:
①抢到锁,继续向下执行
②没抢到,阻塞等待至前面的协程将锁释放
-------------------------------------------
mt.Unlock()
解锁
锁一旦释放,其他抢这把锁的协程就会得到抢锁机会
*/ func main() {
//声明同步锁
var mt sync.Mutex var wg sync.WaitGroup
var money = 2000 for i := 0; i < 10; i++ {
wg.Add(1)
go func(index int) {
fmt.Printf("协程%d开始抢锁\n",index) //抢锁,如果成功,继续向下执行,否则阻塞等待至抢到为止(抢到的人不释放,你就一直阻塞)
//所有抢锁的协程都是资源竞争者
mt.Lock() /*抢锁成功以后执行对数据的访问*/
fmt.Printf("协程%d抢锁成功!\n",index)
fmt.Printf("协程%d开始操作数据!\n",index)
for j := 0; j < 10000; j++ {
money +=1
}
<-time.After(2*time.Second)
fmt.Printf("协程%d将锁释放!\n",index) //数据操作完毕,将锁释放
mt.Unlock()
wg.Done()
}(i)
}
wg.Wait()
fmt.Println(money)
}

  

一个互斥锁的小案例:

package main

import (
"fmt"
"sync"
"time"
) /*
银行账户案例
·创建银行类账户
·存取款方式需要并发安全(不允许并发访问余额)
·查询余额和打印流水可以并发操作
·创建账户实例,并发执行存取款,查询余额,打印流水操作
*/ type Account struct{
money int //账户的互斥锁
mt sync.Mutex
} /*
存钱:必须保证并发安全,不允许并发操作
*/
func (a *Account)SaveMoney(n int) {
//必须先抢到互斥锁
a.mt.Lock() fmt.Println("SaveMoney开始")
<-time.After(3*time.Second)
a.money += n
fmt.Println("SaveMoney结束") //将锁释放
a.mt.Unlock()
} /*
取钱:必须保证并发安全,不允许并发操作
*/
func (a *Account)GetMoney(n int) {
//必须先抢到互斥锁
a.mt.Lock() fmt.Println("GetMoney开始")
<-time.After(3*time.Second)
a.money -= n
fmt.Println("GetMoney结束") //将锁释放
a.mt.Unlock()
} /*查询余额:可以并发执行*/
func (a *Account)Query() {
fmt.Println("Query开始")
<-time.After(3*time.Second)
fmt.Println("当前余额:",a.money)
fmt.Println("Query结束")
} ///*打印流水:可以并发执行*/
//func (a *Account)PrintHistory() {
// fmt.Println("PrintHistory开始")
// <-time.After(3*time.Second)
// fmt.Println("打印流水")
// fmt.Println("PrintHistory结束")
//} func main() {
var wg sync.WaitGroup account := &Account{10000, sync.Mutex{}} for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
account.SaveMoney(100)
wg.Done()
}() } for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
account.GetMoney(100)
wg.Done()
}()
} for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
account.Query()
wg.Done()
}()
} //for i := 0; i < 3; i++ {
// wg.Add(1)
// go func() {
// account.PrintHistory()
// wg.Done()
// }()
//} wg.Wait() fmt.Println("main over")
}

  

Go语言协程并发---互斥锁sync.Mutex的更多相关文章

  1. Go语言协程并发---读写锁sync.RWMutex

    package main import ( "fmt" "sync" "time" ) /* 读写锁 多路只读 一路只写 读写互斥 */ / ...

  2. Go语言协程并发---等待组sync.WaitGroup

    package main import ( "fmt" "sync" "time" ) /*等待组API介绍*/ func main071( ...

  3. Go语言协程并发---管道信号量应用

    package main import ( "fmt" "math" "strconv" "time" ) /* ·10 ...

  4. Go语言协程并发---条件变量

    package main import ( "fmt" "sync" "time" ) func main() { //要监听的变量 bit ...

  5. Go语言协程并发---生产者消费者实例

    package main import ( "fmt" "strconv" "time" ) /* 改进生产者消费者模型 ·生产者每秒生产一 ...

  6. Go语言协程并发---原子操作

    package main import ( "fmt" "sync/atomic" ) /* 用原子来替换锁,其主要原因是: 原子操作由底层硬件支持,而锁则由操 ...

  7. Go语言协程并发---timer秒表与定时器

    秒表 package main import ( "fmt" "time" ) /*每秒大喊我要去浪,共9次,然后退出计时*/ func main() { va ...

  8. Go语言协程并发---select多路复用应用

    package main import ( "fmt" "time" ) /* ·循环从一写两读三条管道中随机选择一条能走的路 ·等所有路都走不通了就退出循环 ...

  9. Go语言协程

    协程的特点 1.该任务的业务代码主动要求切换,即主动让出执行权限 2.发生了IO,导致执行阻塞(使用channel让协程阻塞) 与线程本质的不同 C#.java中我们执行多个线程,是通过时间片切换来进 ...

随机推荐

  1. mvnw 找不到或无法加载主类,找不到符号,类

    如果你出现"找不到或无法加载主类"的问题,很有可能是maven的问题,你可以尝试一下这种办法: 问题:关于maven什么东西都没动,上午可能运行都好好的,下午可能就出现了这个问题, ...

  2. 记某次sql注入绕过ids

    昨天测试sql注入,发现个站,存在ids,一个单引号直接拦截,无论我怎么编码都不行,怕不是废了.. 灵机一动 基础探测 /*'*/ 报错 /*''*/ 返回正常 是字符串类型. 先本地测试 返回所有 ...

  3. Blog总结(前三次作业总结)

    前三次作业总结 1.前言 (1)第一次题目集共有8道题目,难度较为简单,知识点为JAVA的一些编程基础知识点,如输入输出,选择,循环,一维数组等. (2)第二次题目集共有5道题目,难度较第一次题目集有 ...

  4. Intel汇编语言程序设计学习-第二章 IA-32处理器体系结构-下

    2.2  IA-32处理器体系结构 如前所述,IA-32是指始于Intel386直到当前最新的奔腾4的系列的处理器(额...这本书是什么时候写的啊,表示现在应该是I7啊),在IA-32的发展过程中,I ...

  5. HBASE-使用问题-split region

    问题描述: HBASE表的管理以REGION分区为核心,通常面临如下几个问题: 1) 数据如何存储到指定的region分区,即rowkey设计,region splitkey设计 2)设计的split ...

  6. 修改VScode底部状态栏颜色

    点击齿轮进入setting 搜索workbench.colorCustomizations,然后点击编辑setting.json 修改为你喜欢的颜色即可,我这里修改为蓝色 例子: "work ...

  7. Java中实现某方法和重写某方法的区别

    实现(implements) 实现一个方法,在实现某个接口,或者是继承某个抽象类,在接口和在抽象类中定义的方法,本身是没有实现的,也就是没有方法体,你在当前类中就需要去实现这个方法. 重写(overl ...

  8. Log4j讲解

    讲解 通常,我们写代码的过程中,免不了要输出各种调试信息.在没有使用任何日志工具之前,都会使用 System.out.println 来做到. 这么做直观有效,但是有一系列的缺点:1. 不知道这句话是 ...

  9. Windows server 2003域控迁移到2012

    1:  windows server 2003 额外域控升级为 windows server 2003主域控 (因为原域控制器某些服务损坏,于是采用将备用域控升级为主域控的方法) https://we ...

  10. Securecrt 在win7下 字体太少问题

    用WIN7,觉得securecrt里面可用的字体太少了.很多都没有,比如lucida console,经过一番查找,终于找到解决问题的方法了. 原因就是win7里面的很多字体都被设置为隐藏了,所以se ...