8.2 Go 锁

案例(坑):多个goroutine操作同一个map。

go提供了一种叫map的数据结构,可以翻译成映射,对应于其他语言的字典、哈希表。借助map,可以定义一个键和值,然后可以从map中获取、设置和删除这个值,尤其适合数据查找的场景。

但是map的使用有一定的限制,如果是在单个协程中读写map,那么不会存在什么问题,如果是多个协程并发访问一个map,有可能会导致程序退出,并打印下面错误信息。

fatal error: concurrent map writes

错误案例代码

package main

var myMap = make(map[int]int, 10)

//要求计算50的阶乘结果
//阶乘就是1*2*3*4...50 =? func test(n int) {
//定义初始值1
res := 1
//每次循环进行阶乘
for i := 0; i <= n; i++ {
res *= i
}
//最终计算结果,写入map
//由于多个协程同时操作map,引发资源竞争报错
myMap[n] = res }
func main() {
//开启50个协程
for i := 0; i < 10; i++ {
go test(10)
}
}

并发访问map是不安全的操作,在协程中访问map,必须提供某种同步资源机制,使用sync.Mutex互斥锁同步解决协程的竞争问题。

package main

import (
"fmt"
"sync"
"time"
) var lock sync.Mutex func Printer(str string) {
//我现在开始使用打印机了,其他人都等我完事了再来
lock.Lock()
for _, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
//我完事了,你们上吧
lock.Unlock()
fmt.Printf("\n")
} func Alex() {
Printer("hello")
}
func Wupeiqi() {
Printer("oldboy")
} func main() {
//coffe(10)//单线程执行函数
go Alex()
go Wupeiqi()
//主线程等待协程结束后 再退出
time.Sleep(time.Second * 10)
}

结论:

1.可以使用加锁的方式解决goroutine的通讯。
2.主线程等待所有goroutine的时间难以确定,设置固定的等待时间肯定不合理。
3.对全局变量加锁同步来通讯,也不利于多个协程对变量的读写。
4.要让主线程等待所有goroutine退出后在退出,如何知道所有goroutine都退出了呢?
5.因此,channel应运而生!!

8.2 Go 锁的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  3. java中的锁

    java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...

  4. 分布式锁1 Java常用技术方案

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.所以自己结合实际工作中的一些经验和网上看到的一些资 ...

  5. 如何在高并发环境下设计出无锁的数据库操作(Java版本)

    一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Jav ...

  6. 如何定位Oracle数据库被锁阻塞会话的根源

    首先再次明确下,数据库因为要同时保证数据的并发性和一致性,所以操作有锁等待是正常的. 只有那些长时间没有提交或回滚的事物,阻塞了其他业务正常操作,才是需要去定位处理的. 1.单实例环境 2.RAC环境 ...

  7. java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

    一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...

  8. Android 死锁和重入锁

    死锁的定义: 1.一般的死锁 一般的死锁是指多个线程的执行必须同时拥有多个资源,由于不同的线程需要的资源被不同的线程占用,最终导致僵持的状态,这就是一般死锁的定义. package com.cxt.t ...

  9. Xcode 锁终端

    锁终端 输入: <1>cd /Applications/Xcode.app 回车 结果显示: Xcode.app 输入: <2>sudo chown -hR root:whee ...

  10. mysql 行级锁的使用以及死锁的预防

    一.前言 mysql的InnoDB,支持事务和行级锁,可以使用行锁来处理用户提现等业务.使用mysql锁的时候有时候会出现死锁,要做好死锁的预防. 二.MySQL行级锁 行级锁又分共享锁和排他锁. 共 ...

随机推荐

  1. php内置函数call_user_func()

    <?php //call_user_func(callback,name,age) //第一个参数callback作为回掉函数使用,其余的参数是他的参数 function now($a,$b) ...

  2. python学习03字符串基本操作

    '''字符串可以用单引号,双引号,三引号表示 '''#1.读取str1='I am a student!'#每一个字符对应一个下标,可以利用下标的方式来读取字符串对应的值——索引print(str1[ ...

  3. 抖音人脸识别Autojs脚本

    title: 抖音人脸识别Autojs脚本 用Autojs写的抖音人脸颜值检测脚本 ​ 疫情期间宅家久了,昨天闲着没事(好吧,有事情,但是我不想做) ,消费之火熊熊燃烧.一咬牙把Autojs入正了.我 ...

  4. C/C++ 程序执行时间

    C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下: clock_t clock( void ); 这个函数返回从“开启这个程序进 ...

  5. Struts2漏洞利用

    Struts漏洞合集 Struts-S2-013漏洞利用 受影响版本 Struts 2.0.0 - Struts 2.3.14.1 漏洞利用 任意命令执行POC: ${(#_memberAccess[ ...

  6. python的sqlalchemy框架

    先看一下sqlalchemy框架中的映射,sqlalchemy一共有三种映射方式:传统映射(classic).现代化映射(modern).自定义映射.在这里,只为大家讲一下classic映射和mode ...

  7. Kubernetes 持久化存储是个难题,解决方案有哪些?\n

    像Kubernetes 这样的容器编排工具正在彻底改变应用程序的开发和部署方式.随着微服务架构的兴起,以及基础架构与应用程序逻辑从开发人员的角度解耦,开发人员越来越关注构建软件和交付价值. Kuber ...

  8. 爱创课堂每日一题第五十四天- 列举IE 与其他浏览器不一样的特性?

    IE支持currentStyle,FIrefox使用getComputStyle IE 使用innerText,Firefox使用textContent 滤镜方面:IE:filter:alpha(op ...

  9. Process Synchronization-Example 2

    问题描述 理发店有一位理发师,一把理发椅和N把供等候的顾客坐的椅子. 如果没有顾客,理发师在理发椅上睡觉: 当有一个顾客到来时,他必须先唤醒理发师: 如果顾客来时理发师正在理发,如果有空椅子,坐下等待 ...

  10. 迁移WPF项目到.NET CORE

    综述 .NET CORE 3.0开始,桌面端支持WPF了.很多.NET FRAMEWORK的项目已经跑了一阵子了,不是很有必要支持.NET CORE,不过最近用一个程序,为了贯彻一些C# 8的特性,需 ...