一:原子操作CAS(compare-and-swap)
原子操作分三步:读取addr的值,和old进行比较,如果相等,则将new赋值给*addr,他能保证这三步一起执行完成,叫原子操作也就是说它不能再分了,当有一个CPU在访问这块内容addr时,其他CPU就不能访问
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$-
MOVD addr+(FP), R3
MOVD old+(FP), R4
MOVD new+(FP), R5
SYNC
LDAR (R3), R6
CMP R6, R4
BNE (PC)
STDCCC R5, (R3)
BNE -(PC)
ISYNC
MOVD $, R3
MOVB R3, swapped+(FP)
RET
MOVB R0, swapped+(FP)
RET
 
二:普通锁
加锁(Mutex.Lock)
1:原子操作加锁:原子操作判断是否已经被加锁,如果没有加锁,原子操作加锁,直接返回,很快吗!
2:执行旋转锁:已经被加锁,判断是否可以执行旋转锁,执行旋转锁,原子判断是否可以加锁,若可以,加锁返回
3:当前G休眠等待被唤醒:在执行旋转锁期间,锁还是没释放,那就只能让当前协程休眠,等待被唤醒,当锁被释放后,当前G被唤醒继续执行
 
释放锁(Mutex.UnLock)
1:将加锁状态去掉,判断是否有等待的协程,如没有直接返回
2:若有等待协程,将状态设置成唤醒状态
3:唤醒一个等待协程
 
 
三:读写锁
读写锁基于普通锁实现
加写锁(RWMutex.Lock)
1:加普通锁
2:改读锁的数量readerCount -= 1 << 30
3:如果有正在读的锁,等待直到读锁完成,读写不能同时进行
 
释放写锁(RWMutex.UnLock)
1:改读锁的数量readerCount += 1 << 30,加锁的时候减了这么多,释放锁的时候加回来
2:如果readerCount>=  1 << 30,抛异常,释放没有加锁的锁
3:唤醒所有正在等待读的协程
4:释放普通锁
 
加读锁(RWMutex.RLock)
1:原子操作读锁数量加1,readerCount+=1
2:如果rederCount<0,说明有写功能正在执行,协程进入睡眠状态,等待写完之后被唤醒
3:如果没有正在执行的写锁,就完事了,整个加锁操作就只执行了一个原子操作,还是很快的
 
释放读锁(RWMutex.RUnLock)
1:原子操作读锁数量减1
2:如果读锁数量==-1,或==-1 << 30,说明释放了一个没有加读锁的锁,或者释放了一个正在写的锁,直接报错
3:如果有正在等待的写锁,唤醒它,否则整个释放读锁也就执行了一个原子操作
 
所以说,锁是基于原子操作的,原子操作保证了数据的一致性,读写锁基于普通锁来实现,对于一个写少读多的程序来说,读写锁会比普通锁快很多
 
加锁原理
1:先是CAS的方式尝试获取锁,如果获取到了,就锁住,并继续执行被锁住的代码,然后在释放锁
2:CAS没有拿到锁,就只能等待了,比如有10个协程(G)在等这个待锁,go并不是一把锁创建一个队列,而是默认创建251个队列,通过hash的方式将G加入队列,确保等待同一把锁的G在同一个队列,然后将当前G执行上下文信息保存到G.sched,下次就可以继续从这里执行,这样这个等待的G就这样被扔到队列中了,而不是将这个G状态改成等待状态等待被唤醒,G去睡觉了,P还得继续执行,于是会找一个P,继续执行
 
解锁原理
1:通过锁定位到对应的队列,所有等待这把锁的G都在这个队列中,查找是否有等待的G,没有就返回
2:有就将G状态改成可运行,并加入到运行队列,等待被调度
 
关于G调度请看我的这篇文章:go并发调度原理学习
 
 

原子操作&普通锁&读写锁的更多相关文章

  1. 使用ZooKeeper实现Java跨JVM的分布式锁(读写锁)

    一.使用ZooKeeper实现Java跨JVM的分布式锁 二.使用ZooKeeper实现Java跨JVM的分布式锁(优化构思) 三.使用ZooKeeper实现Java跨JVM的分布式锁(读写锁) 读写 ...

  2. Java并发-显式锁篇【可重入锁+读写锁】

    作者:汤圆 个人博客:javalover.cc 前言 在前面并发的开篇,我们介绍过内置锁synchronized: 这节我们再介绍下显式锁Lock 显式锁包括:可重入锁ReentrantLock.读写 ...

  3. linux 内核的另一个自旋锁 - 读写锁

    除spinlock外,linux 内核还有一个自旋锁,名为arch_rwlock_t.它的头文件是qrwlock.h,包含在spinlock.h,头文件中对它全称为"Queue read/w ...

  4. 深入理解java:2.3.2. 并发编程concurrent包 之重入锁/读写锁/条件锁

    重入锁 Java中的重入锁(即ReentrantLock)   与JVM内置锁(即synchronized)一样,是一种排它锁. ReentrantLock提供了多样化的同步,比如有时间限制的同步(定 ...

  5. 可重入锁 公平锁 读写锁、CLH队列、CLH队列锁、自旋锁、排队自旋锁、MCS锁、CLH锁

    1.可重入锁 如果锁具备可重入性,则称作为可重入锁. ========================================== (转)可重入和不可重入 2011-10-04 21:38 这 ...

  6. JAVA线程锁-读写锁

    JAVA线程锁,除Lock的传统锁,又有两种特殊锁,叫读写锁ReadWriteLock 其中多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 例子: /** * java线程锁分为读写锁 ReadWri ...

  7. Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

    (1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...

  8. Go同步等待组/互斥锁/读写锁

    1. 临界资源 package main import ( "fmt" "time" ) func main() { /* 临界资源: */ a := 1 go ...

  9. JAVA线程锁-读写锁应用,简单的缓存系统

    在JAVA1.5版本以后,JAVA API中提供了ReadWriteLock,此类是一个接口,在它的实现类中ReentrantReadWriteLock中有这样一段代码 class CachedDat ...

随机推荐

  1. VMware workstation的基础使用

    1. VMware workstation虚拟化平台简介2. VMware workstation提供网络资源3. VMware workstation提供存储资源4. VMware workstat ...

  2. 如何运行vue项目

    首先,列出来我们需要的东西:   node.js环境(npm包管理器) vue-cli 脚手架构建工具 cnpm  npm的淘宝镜像   安装node.js 从node.js官网下载并安装node,安 ...

  3. 谈谈volatile关键字以及常见的误解

    转载请保留以下声明 作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9092520.html 近期看到C++标准中对volatile关键字的定义, ...

  4. k8s经典实战—搭建WordPress

    k8s经典实战—搭建WordPress说明:需要在k8s上部署lnmp环境,建议跟着步骤来端口最好不要改,希望你也能搭建成功,完成这个搭建后你对Kubernetes的技术基本上是入门了.首先看下效果图 ...

  5. 软件测试自动化的最新趋势对开源测试管理软件ITEST的启示

    https://www.infoq.cn/article/c-LHJS2ksuDxp1WkrGl4 理面提到几点,DevOps 的关键原则是开发团队.测试团队和运营团队协作,无缝发布软件.这意味着集中 ...

  6. MySQL 多实例的安装

    Step 1 . 准备工作 关闭防火墙; 安装 MySQL依赖于libaio 库:下载,解压,重命名 MySQL的执行文件:新建用户组和用户 等准备工作在此不再赘述. 可执行文件目录为 /data/m ...

  7. 华为云.NET Core支持情况调查

    各大公有云都提供了开发者开发的SDK,今天我们来看看华为云对.NET Core的支持情况怎么样? .NET SDK地址 https://developer.huaweicloud.com/sdk#.N ...

  8. JQuery 常用的那些东西

    CDN Google CDN Microsoft CDN CDNJS CDN jsDelivr CDN 选择器 jQuery 元素选择器和属性选择器允许您通过标签名.属性名或内容对 HTML 元素进行 ...

  9. PTA 深入虎穴 (正解)和树的同构

    在上一篇博客中分享了尝试用单链表修改程序,虽然在Dev上运行没有错误,但是PTA设置的测试点有几个没有通过,具体不清楚问题出现在哪里,所以现在把之前正确的程序放在这里. 7-2 深入虎穴 (30 分) ...

  10. 前端技术大行其道,再不拥抱TypeScript你就老了!

    本篇文章旨在介绍下TypeScript这门新兴的程序设计语言,不需要你有多么强的专业知识,只需要你有半支烟的功夫. 好了,废话不多说,赶紧进入正题.为什么你需要拥抱TypeScript?那么你首先需要 ...