go 并发学习-互斥锁

2023-05-16

go 并发学习-互斥锁

  • 并发输出 inums 自增
    • 编写代码
    • 运行输出
    • 并不能正常输出
  • 使用互斥锁
    • 修改代码
    • 结果
    • 结果正常
  • 使用锁时注意
    • 上锁的资源独立函数
    • 有些时候用读写锁
    • 如果可以改为使用 channel

并发输出 inums 自增

编写代码

package main

import (
	"fmt"
	"time"
)

var inums = 0

func inumadd() int {
	inums++
	fmt.Println(inums)
	return inums
}

func test() {
	for {
		inumadd()
		time.Sleep(1000000000) //等待1秒
	}
}

func main() {
	go test()
	go test()
	go test()
	go test()
	go test()
	go test()
	test()
}

运行输出


API server listening at: 127.0.0.1:40291
1
3
4
5
6
2
7
9
8
13
14
12
10
11

并不能正常输出

  • 互斥锁
  1. 互斥锁有两种操作,获取锁和释放锁
  2. 当有一个goroutine获取了互斥锁后,其它goroutine都不可以获取互斥锁,只能等待这个goroutine将互斥锁释放
  3. 互斥锁适用于读写操作数量差不多的情况

使用互斥锁

修改代码

package main

import (
	"fmt"
	"sync"
	"time"
)

var inums = 0
var mutex sync.Mutex

func inumadd() int {
	//  互斥锁
	mutex.Lock()
	defer mutex.Unlock()
	inums++
	fmt.Println(inums)
	return inums
}

func test() {
	for {
		inumadd()
		time.Sleep(1000000000) //等待1秒
	}
}

func main() {
	go test()
	go test()
	go test()
	go test()
	go test()
	go test()
	test()
}

结果

API server listening at: 127.0.0.1:31063
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

结果正常

使用锁时注意

上锁的资源独立函数

func inumadd() int {
	//  互斥锁
	mutex.Lock()
	defer mutex.Unlock()
	inums++
	fmt.Println(inums)

	// 比如在这 httpget,不推荐
	// httpget(inums);
	
	return inums
}

func test() {
	for {
		inumadd()


		// 应该这里 httpget
		httpget(inums);

		time.Sleep(1000000000) //等待1秒
	}
}

有些时候用读写锁

  1. 读写锁有四种操作 读上锁 读解锁 写上锁 写解锁
  2. 写锁最多有一个,读锁可以有多个(最大个数据说和CPU个数有关)
  3. 写锁的优先级高于读锁,这是因为为了防止读锁过多,写锁一直堵塞的情况发生
  4. 当有一个goroutine获得写锁时,其他goroutine不可以获得读锁或者写锁,知道这个写锁释放
  5. 当有一个goroutine获得读锁时,其他goroutine可以获得读锁,但是不能获得写锁。所以由此也可得知,如果当一个goroutine希望获取写锁时,不断地有其他goroutine在获得读锁和释放读锁会导致这个写锁一直处于堵塞状态,所以让写锁的优先级高于读锁可以避免这种情况,
  6. 读写锁适用于读多写少的情景。

如果可以改为使用 channel

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

go 并发学习-互斥锁 的相关文章

随机推荐

  • 查询字符串中指定字符的索引 python

    def indexMany s str str是要查询的字符 length 61 len s 获取该字符串的长度 str1 61 s 拷贝字符串 list 61 sum 61 0 用来计算每次截取完字符串的总长度 try while str
  • C语言 字符串-字符串的复制

    字符串复制函数 xff1a strcpy 目标字符串的首地址 被复制的字符串的首地址 复制p到a xff1a char p 61 34 12345 34 char a 20 strcpy a p printf 34 s n 34 a str
  • cmake是什么,为什么现在都用cmake,cmake编译原理和跨平台示例

    一 cmake是什么 xff1f CMake是一个开源 跨平台的工具系列 xff0c 是用来构建 测试和打包软件 CMake使用平台无关的配置文件来控制软件编译过程 xff0c 并生成可在您选择的编译器环境中使用项目文件 xff0c 比如可
  • cmake和makefile区别和cmake指定编译器(cmake -G)

    一 cmake和makefile区别 要说明区别 xff0c 我们先要区分下面三类工具 xff1a 1 项目构建生成工具 首先cmake是项目构建生成工具 xff0c cmake的代码可以与平台系统和编译器无关 类似cmake的工具还有au
  • PHP+iis部署最干货的步骤

    1 php gt gt gt 下载 官网下载 gt gt gt 部署 解压到文件夹d xff0c 然后找文件php ini production xff0c 开发者模式 修改文件为php ini作为配置文件 date timezone 61
  • spring cloud - consul 之 网关(3)

    spring cloud consul 之 网关 xff08 3 xff09 1 添加maven 依赖 lt dependency gt lt groupId gt org springframework boot lt groupId g
  • SpringCloud - consul 服务注册生产(2)

    SpringCloud consul 服务注册生产 xff08 2 xff09 1 添加maven 依赖 lt dependency gt lt groupId gt org springframework boot lt groupId
  • springcloud consul 搭建docker 集群(1)

    springcloud consul 搭建docker 集群 xff08 1 xff09 1 建3个server节点 和1个client节点 配置docker 网络 sudo docker network create subnet 61
  • Spring+OpenCV+Linux(libopencv_java460.so、opencv-460.jar)人脸识别、人脸对比实现

    准备工作 Linux生成libopencv java460 so opencv 460 jar lbpcascade frontalface xml文件 opencv源码地址 xff1a https github com opencv op
  • net core3.0 修改 web 端口

    修改程序发布之后的端口 新建项目 xff0c 啥都不干启动成功后 xff0c 在 appsettings json 中 添加配置 urls http 8080 34 Logging 34 34 LogLevel 34 34 Default
  • go 语法入门

    go 语法 循环 package main import 34 fmt 34 func main i 61 0 for i lt 1000 i 43 43 fmt Println 34 循环次数 xff1a 34 i 定义局部变量 var
  • windows vscode mingw c++入门(1)

    windows vscode mingw c 43 43 入门 xff08 1 xff09 安装 mingw32 https osdn net projects mingw downloads 68260 mingw get setup e
  • windows vscode mingw c++入门(2)

    windows vscode mingw c 43 43 入门 xff08 2 xff09 导包 新建文件夹 first 与 mian cpp 同级新建文件夹 first新建两个文件q h pragma once 防止重复导入 void q
  • netcore3 sqlite

    net core3 1 EF 43 SQLite nuget 安装这3个包 microsoft EntityFrameworkCore Microsoft EntityFrameworkCore Sqlite Microsoft Entit
  • windows 上 consul

    本机开发模式 consul官网 本机开发者模式 consul exe agent dev 局域网 consul exe agent dev client 0 0 0 0
  • go 通道(channel),go 线程间通信

    go 通道 xff08 channel xff09 是用来传递数据的一个数据结构 通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯 操作符 lt 用于指定通道的方向 xff0c 发送或接收 span clas
  • windows 批量关闭 python 程序工具

    windows 批量关闭 python 程序工具 在windows上启动大量pythonw 后台程序 xff0c 都不知道哪个是哪个 l par query par a show all lk par 终止查询到的程序 python 源码
  • windows+vscode+MinGW+cmake(学习1)

    统一下载 64 位安装 1 安装vscode 官网 安装插件 2 安装 mingw 官网 或者 3 安装cmake 官网 安装好之后 创建 项目文件夹 cmaketest1 创建文件 xff08 1 xff09 main c span cl
  • Springcloud、Springmvc+Nacos注册中心实现服务注册

    目录 背景 实现 Nacos环境搭建 Springcloud服务注册 Maven配置 代码实现 Springmvc服务注册 Maven依赖 代码实现 背景 不管是springcloud还是springmvc实现服务的自动注册 xff0c 都
  • go 并发学习-互斥锁

    go 并发学习 互斥锁 并发输出 inums 自增编写代码运行输出并不能正常输出 使用互斥锁修改代码结果结果正常 使用锁时注意上锁的资源独立函数有些时候用读写锁如果可以改为使用 channel 并发输出 inums 自增 编写代码 pack