前面的有篇文章在讲资源竞争的时候,提到了互斥锁。互斥锁的根本就是当一个goroutine访问的时候,其他goroutine都不能访问,这样肯定保证了资源的同步,避免了竞争,不过也降低了性能。

仔细剖析我们的场景,当我们读取一个数据的时候,如果这个数据永远不会被修改,那么其实是不存在资源竞争的问题的。因为数据是不变的,不管怎么读取,多少goroutine同时读取,都是可以的。

所以其实读取并不是问题,问题主要是修改。修改的数据要同步,这样其他goroutine才可以感知到。所以真正的互斥应该是读取和修改、修改和修改之间,读取和读取是没有互斥操作的。

所以这就延伸出来另外一种锁,叫做读写锁。

读写锁可以让多个读操作同时并发,同时读取,但是对于写操作是完全互斥的。也就是说,当一个goroutine进行写操作的时候,其他goroutine既不能进行读操作,也不能进行写操作。

package main

import (
"sync"
"fmt"
"math/rand"
)
var count int
var wg sync.WaitGroup
var rw sync.RWMutex func main() {
wg.Add()
for i:=;i<;i++ {
go read(i)
}
for i:=;i<;i++ {
go write(i)
}
wg.Wait()
} func read(n int) {
rw.RLock()
fmt.Printf("读goroutine %d 正在读取...\n",n)
v := count
fmt.Printf("读goroutine %d 读取结束,值为:%d\n", n,v)
wg.Done()
rw.RUnlock()
} func write(n int) {
rw.Lock()
fmt.Printf("写goroutine %d 正在写入...\n",n)
v := rand.Intn()
count = v
fmt.Printf("写goroutine %d 写入结束,新值为:%d\n", n,v)
wg.Done()
rw.Unlock()
}

我们在read里使用读锁,也就是RLock和RUnlock,写锁的方法名和我们平时使用的一样,是Lock和Unlock。这样,我们就使用了读写锁,可以并发地读,但是同时只能有一个写,并且写的时候不能进行读操作。现在我们再运行代码,可以从输出的数据看到,可以读到新值了。

我们同时也可以使用go build -race检测,也没有竞争提示了。

Golang之并发资源竞争(读写锁)的更多相关文章

  1. Golang之并发资源竞争(互斥锁)

    并发本身并不复杂,但是因为有了资源竞争的问题,就使得我们开发出好的并发程序变得复杂起来,因为会引起很多莫名其妙的问题. package main import ( "fmt" &q ...

  2. Java并发编程之读写锁

    读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作.只要没有writer,读取锁可以由多个reader线程同时保持.写入锁是独占的. 可重入读写锁 ReentrantReadWriteLoc ...

  3. Java并发:ReadWriteLock 读写锁

    读写锁在同一时刻可以允许多个线程访问,但是在写线程访问,所有的读线程和其他写线程均被阻塞. 读写锁不像 ReentrantLock 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ...

  4. java并发锁ReentrantReadWriteLock读写锁源码分析

    1.ReentrantReadWriterLock 基础 所谓读写锁,是对访问资源共享锁和排斥锁,一般的重入性语义为如果对资源加了写锁,其他线程无法再获得写锁与读锁,但是持有写锁的线程,可以对资源加读 ...

  5. [Go] 使用读写锁对map资源进行安全处理

    当需要有一个全局性的map集合资源进行增删改数据时,需要对该map资源增加读写锁,防止并发时出现安全问题 下面的类就是举例 , 属性中的Conns模拟存储一些资源,对这些资源进行并发的增加数据,使用写 ...

  6. Java并发包源码学习系列:ReentrantReadWriteLock读写锁解析

    目录 ReadWriteLock读写锁概述 读写锁案例 ReentrantReadWriteLock架构总览 Sync重要字段及内部类表示 写锁的获取 void lock() boolean writ ...

  7. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

  8. 三、curator recipes之共享的可重入读写锁

    简介 curator实现了跨JVM的可重入读写互斥锁.它使用zookeeper去进行加锁,所以指定相同路径的处理线程将会基于“公平锁”的机制去竞争锁资源. 读写锁包含了读锁.写锁两个,它们的互斥关系如 ...

  9. 从火车站车次公示栏来学Java读写锁

    Java多线程并发之读写锁 本文主要内容:读写锁的理论:通过生活中例子来理解读写锁:读写锁的代码演示:读写锁总结.通过理论(总结)-例子-代码-然后再次总结,这四个步骤来让大家对读写锁的深刻理解. 本 ...

随机推荐

  1. 浅谈 温故知新——HTML5!

    古人有云:温故而知新.活到老,学到老,作为一枚前端的程序猿,不停的学习能够让我们对我们的技术有一个更加丰富的认识.这几天,项目已经完成,但我发现自己的知识体系存在一些短板,特别是在H5方面,所以我又回 ...

  2. 【ocp-12c】最新Oracle OCP-071考试题库(38题)

    38.choose the best answer View the Exhibit and examine the data in the PROMOTIONS table. PROMO_BEGIN ...

  3. kvm快照备份及常用命令

    转载自:http://www.myjishu.com/?p=431 好文章 kvm快照备份及常用命令 kvm快照,分两种: 1种lvm快照,如果分区是lvm,可以利用lvm进行kvm的快照备份 2种由 ...

  4. linux 下的 crontab 定时任务工具

    以下内容转自:https://www.cnblogs.com/longjshz/p/5779215.html 在LINUX中,周期执行的任务一般由cron这个守护进程来处理[ps -ef|grep c ...

  5. java下载文件注意点

    前台: 不建议使用ajax,可以使用window.location.href 后台: 三个参数--> response path filename--filename如果要防止乱码,可以用Str ...

  6. combining-filters

    The previous two examples showed a single filter in use. In practice, you will probably need to filt ...

  7. 如何实现三个div都自适应(滴滴面试题)

    <div class="table"> <div class="accordant"> <div class="box& ...

  8. SpringBoot idea maven打包war及运行war包

    pom.xml修改打包类型pom改为war <artifactId>Test02</artifactId> <packaging>war</packaging ...

  9. PDF转HTML的方法。

    上个项目客户提出了一个需求,要求把PDF格式的文件转化为HTML格式. 上网查了一下,要么使用软件处理,要么是HTML格式转化为PDF.因为涉及到图文识别问题,所以说仅仅依靠前端不能实现.在网上查了几 ...

  10. mysql5.7.20多实例编译安装

    好记性不如烂笔头! MySQL多实例 实际上就是在同一台服务器上运行多个mysql服务进程. 相同点:公用同一套MySQL安装程序. 不同点:使用不同的配置文件(也可以相同).启动程序(也可以相同). ...