https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/09.3.md

9.3 锁和 sync 包

在一些复杂的程序中,通常通过不同线程执行不同应用来实现程序的并发。当不同线程要使用同一个变量时,经常会出现一个问题:无法预知变量被不同线程修改的顺序!(这通常被称为资源竞争,指不同线程对同一变量使用的竞争)显然这无法让人容忍,那我们该如何解决这个问题呢?

经典的做法是一次只能让一个线程对共享变量进行操作。当变量被一个线程改变时(临界区),我们为它上锁,直到这个线程执行完成并解锁后,其他线程才能访问它。

特别是我们之前章节学习的 map 类型是不存在锁的机制来实现这种效果(出于对性能的考虑),所以 map 类型是非线程安全的。当并行访问一个共享的 map 类型的数据,map 数据将会出错。

在 Go 语言中这种锁的机制是通过 sync 包中 Mutex 来实现的。sync 来源于 "synchronized" 一词,这意味着线程将有序的对同一变量进行访问。

sync.Mutex 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。

假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 Mutex 来实现的一个典型例子如下:

import  "sync"

type Info struct {
mu sync.Mutex
// ... other fields, e.g.: Str string
}

如果一个函数想要改变这个变量可以这样写:

func Update(info *Info) {
info.mu.Lock()
// critical section:
info.Str = // new value
// end critical section
info.mu.Unlock()
}

还有一个很有用的例子是通过 Mutex 来实现一个可以上锁的共享缓冲器:

type SyncedBuffer struct {
lock sync.Mutex
buffer bytes.Buffer
}

在 sync 包中还有一个 RWMutex 锁:他能通过 RLock() 来允许同一时间多个线程对变量进行读操作,但是只能一个线程进行写操作。如果使用 Lock() 将和普通的 Mutex 作用相同。包中还有一个方便的 Once 类型变量的方法 once.Do(call),这个方法确保被调用函数只能被调用一次。

相对简单的情况下,通过使用 sync 包可以解决同一时间只能一个线程访问变量或 map 类型数据的问题。如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题,这是在 Go 语言中所提倡用来实现并发的技术。我们将在第 14 章对其深入了解,并在第 14.7 节中对这两种方式进行比较。

如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题的更多相关文章

  1. Response.Write()方法响应导致页面字体变大的解决办法

    关于ASP.NET中用Response.Write()方法响应导致页面字体变大的解决办法     最近研究了ASP.NET,发现一个问题,比方说在页面里面有个Button,要点击以后要打开新窗口,而且 ...

  2. 无辜的RAD(RAD是让你去创造和使用可复用的组件,不是让程序员“变白痴”)good

    无辜的RAD 2005-3-21 说实话,RAD很无辜.从出生的那天其就被骂,天天被指着鼻子说“不就是拖个控件嘛”,就好像当年说学电脑“不就是插个鼠标嘛”.也怪程序员大都天性犯贱,就爱一遍又一便的写基 ...

  3. 头疼3-4次的问题,数据从DB导出到EXCEL,再从EXCEL导入到DB,数据格式发生错误 ,导致 程序出错。

    反思: 1 解决 问题的思路 绕远了: 在这个问题出现前,程序是运行正确 的 问题出现前,我误删了DB 的 testcase表的所有 case ,然后 再把邮件 中的excel数据导入到 DB 然后 ...

  4. WPF 线程中异常导致程序崩溃

    一般我们WPF中都加全局捕获,避免出现异常导致崩溃. Application.Current.DispatcherUnhandledException += Current_DispatcherUnh ...

  5. thinkphp关闭调试模式(APP_DEBUG => false),导致程序出错

    thinkphp关闭调试模式(APP_DEBUG => false),导致程序出错,开启调试模式,不报错,怎么解决? 查看Logs日志记录: [ --29T09::+: ] 113.108.11 ...

  6. Android Studio 创建不恰当的虚拟设备导致程序不正常运行

    操作系统:Windows 10 x64 IDE:Android Studio 3.2.1 使用Android Studio新建第一个Android程序,一开始在虚拟设备上面调试,不管程序怎么修改,运行 ...

  7. linux 使用不安全的sprintf函数,存储字符越界导致程序莫名崩溃问题

    linux c++编程 问题背景: 在处理一个公共模块的代码中,其中有以下代码片段 //代码片段-组合一组字符串并存放到szSignKey数组中 ] = {}; sprintf(szSignKey, ...

  8. 【PyCharm疑问】在pycharm中带有中文时,有时会导致程序判断错误,是何原因?

    1.会导致程序打印false错误的代码如下: # -*- coding:utf-8 -*- import os import sys from uiautomator import device as ...

  9. 内核futex的BUG导致程序hang死问题排查

    https://mp.weixin.qq.com/s/sGS-Kw18sDnGEMfQrbPbVw 内核futex的BUG导致程序hang死问题排查 原创: 王领先 58架构师 今天   近日,Had ...

随机推荐

  1. 利用Django徒手写个静态页面生成工具

    每个Geek对折腾自己的博客都有着一份执念 背景介绍 曾经多次在不同的平台写博客,但全部都以失败而告终.去年七月选择微信公众号做为平台开始了又一次的技术分享,庆幸一直坚持到现在,但随着文章发表的越来越 ...

  2. luogu P1214 [USACO1.4]等差数列 Arithmetic Progressions

    题目描述 一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列. 在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双 ...

  3. Docker 容器网络

    默认网络 当安装docker时,它会自动创建3个网络.可以使用docker network ls 来查看.   zane@zane-V:~$ docker network ls NETWORK ID ...

  4. IOS开发~灵活使用 dismissViewControllerAnimated / dismissModalViewControllerAnimated

    当遇到: A presentViewController B ,  B presentViewController C,  C presentViewController D,问如何从D一下子回到A, ...

  5. weblogic控制台登录很慢

      分类: Oracle 原文地址:weblogic控制台登录很慢 作者:paomananshan 实际是JVM在Linux下的bug 他想调用一个随机函数 但取不到 暂时的解决办法是 1)较好的解决 ...

  6. Linux常用的几个vi小命令

    输入跳转命令: 命令行前 Ctrl+A 命令行后 Ctrl+E VI命令中: 当前行 行首  "0" 当前行 行尾  "Shift+4" 当前文档首行首字符:& ...

  7. 2017.2.28 activiti实战--第五章--用户与组及部署管理(二)部署流程资源

    学习资料:<Activiti实战> 第五章 用户与组及部署管理(二)部署流程资源 内容概览:讲解流程资源的读取与部署. 5.2 部署流程资源 5.2.1 流程资源 流程资源常用的有以下几种 ...

  8. 转: java服务器端成长指南

    from:  http://m.blog.csdn.net/article/details?id=45797155 前言 这是一份针对新手的服务端开发入门与进阶指南.遇到问题及时问你的 mentor ...

  9. 出自 HTML4 规范的可用颜色字符串值列表(常用颜色名称及对应的十六进制值)

    据称由于 HTML5 没有修改专属的颜色,HTML4 的颜色都可以在 HTML5 中正确显示. 出自 HTML4 规范的可用颜色字符串值列表如下,此表来源是 http://www.lovean.com ...

  10. Vmware+gdb调试Linux内核——工欲善其事,必先利其器

    今天我最终忍受不了qemu的低速跟不可理喻的各种bug,開始寻找新的调试内核的方法.然后想到了Vmware,那么成熟的虚拟机怎么可能调试不了内核.于是尝试了一番,发现结果很的棒!所以立刻奋笔疾书.把这 ...