作者:困了电视剧

专栏:《JavaEE初阶》

文章分布:这是关于操作系统锁策略的文章,包括乐观锁、读写锁、重量级锁、自旋锁、公平锁、可重入锁等,希望对你有所帮助!

目录

乐观锁和悲观锁

悲观锁

乐观锁

应用

读写锁

重量级锁和轻量级锁

用户态和内核态

自旋锁和挂起等待锁

公平锁和不公平锁

可重入锁和不可重入锁


以下的锁策略,不仅仅适用于java,别的语言和工具只要涉及到锁也同样适用。

乐观锁和悲观锁

悲观锁

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这 样别人想拿这个数据就会阻塞直到它拿到锁。

举个栗子:悲观锁就相当于我们想去找老师问问题,我们先在社交软件上询问老师有没有时间,如果老师有时间再去问,没有就不问,这个先在社交软件上询问就是所谓的加锁操作,每次询问都需要消耗资源。

乐观锁

假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并 发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。

举个栗子:乐观锁就相当于我每次有问题我不提前询问老师有没有时间,我直接去老师的办公室问,如果老师这时候正好有时间我就正好问,没有我就不急着问,下次再来,这里的就相当于不加锁,但是识别出数据访问冲突。

应用

乐观锁和悲观锁没有好坏优劣之分,如果目前数据修改的比较频繁,那悲观锁的每次“询问”消耗的资源就会远远小于乐观锁每次“跑去办公室”消耗的资源,而如果,数据修改的并不频繁,那乐观锁就可以省去每次进行“询问”的资源,什么时候用什么策略根据当前情况决定。

读写锁

多线程之间,数据的读取方之间不会产生线程安全问题,但数据的写入方互相之间以及和读者之间都需要进行互斥。如果两种场景下都用同一个锁,就会产生极大的性能损耗。所以读写锁因此而产生。
读写锁( readers-writer lock ),看英文可以顾名思义,在执行加锁操作时需要额外表明读写意图,复数读者之间并不互斥,而写者则要求与任何人互斥。

一个线程对于数据的访问主要进行两种操作,即读数据和写数据,当我们仅仅对于一个数据进行读操作的时候,由于数据并不会发生改变,怎么读都一样并不会造成线程不安全,所以我们无需考虑加锁的问题,只有我们进行写操作的时候才会因为数据更改造成线程不安全的问题

在java中,专门为读锁和写锁写了两个类,即

ReentrantReadWriteLock.ReadLock 类表示一个读锁 . 这个对象提供了 lock / unlock 方法进行加锁解锁.
ReentrantReadWriteLock.WriteLock 类表示一个写锁 . 这个对象也提供了 lock / unlock 方法进行加锁解锁.

并且读锁和写锁之间遵循如下的条件。

读加锁和读加锁之间 , 不互斥。
写加锁和写加锁之间 , 互斥。
读加锁和写加锁之间 , 互斥。

重量级锁和轻量级锁

轻量级锁和重量级锁在使用逻辑上和乐观锁与悲观锁很相似。

锁的核心特性 " 原子性 ", 这样的机制追根溯源是 CPU 这样的硬件设备提供的 .
1.CPU 提供了 " 原子操作指令 ".
2.操作系统基于 CPU 的原子指令 , 实现了 mutex 互斥锁 .
3.JVM 基于操作系统提供的互斥锁 , 实现了 synchronized 和 ReentrantLock 等关键字和类

轻量级锁只是一个“检测”,在实际运行的过程中,轻量级锁不需要申请互斥量,此时就相当于“检测”,如果此时锁冲突了,不得不申请互斥量即进行阻塞等待了,那这个轻量级锁就会变成重量级锁进行操作,没有就按轻量级锁的来,使用重量级锁需要进行用户态和内核态的切换等一系列消耗资源的操作,这样就大大节省了资源。

用户态和内核态

用户态和内核态是操作系统的两种状态,处于内核态的 CPU 可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且占用 CPU 不会发生抢占情况,一般处于特权级 0 的状态我们称之为内核态。

处于用户态的 CPU 只能受限的访问内存,并且不允许访问外围设备,用户态下的 CPU 不允许独占,也就是说 CPU 能够被其他程序获取。

举个栗子:

去银行办理业务,窗口之外顾客所处的位置就相当于用户态,而银行的工作人员所处的窗口内就是内核态,去办理一个业务,假设这个业务银行的工作人员能做到,你也能做到。在这种时候,如果你交给银行的工作人员来做,由于他还有很多其他的事情要做,所以等到帮你做事的时候不知道要等到什么时候,并且这个时间是不确定不可控的。

而如果这时,你去做这件事,你由于现在手头上只有这一件事,你就会立即去做,效率很高,需要的资源也很少,并且时间是确定的可控的。

自旋锁和挂起等待锁

自旋锁是轻量级锁的一种典型实现方式。

挂起等待锁是重量级锁的一种典型实现方式。

自旋锁就相当于,只要加了锁,线程正在阻塞就会像执行空循环一样一直“检测”,直到锁一被释放,我自旋锁就立刻接任。

而挂起等待锁则是,我发现锁正在被占用,我就立刻阻塞等待,不会一直进行“检测”。

所以由此可见,自旋锁是不进行阻塞等待的,挂起等待锁则会实实在在的进行挂起等待。

公平锁和不公平锁

假设现在有A,B,C三个线程,A现在获取到了锁,正在执行任务,那当A执行完了以后,B,C怎么执行呢?

公平锁 : 遵守 " 先来后到 ". B 比 C 先来的 . 当 A 释放锁的之后 , B 就能先于 C 获取到锁 .
非公平锁 : 不遵守 " 先来后到 ". B 和 C 都有可能获取到锁 .
操作系统内部的线程调度就可以视为是随机的 . 如果不做任何额外的限制 , 锁就是非公平锁 . 如果要想实现公平锁, 就需要依赖 额外的数据结构 , 来记录线程们的先后顺序 .
公平锁和非公平锁没有好坏之分 , 关键还是看适用场景 .

可重入锁和不可重入锁

可重入锁的字面意思是 “ 可以重新进入的锁 ” ,即 允许同一个线程多次获取同一把锁
比如一个递归函数里有加锁操作,递归过程中这个锁会阻塞自己吗?如果不会,那么这个锁就是 可重入 (因为这个原因可重入锁也叫做 递归锁
Java 里只要以 Reentrant 开头命名的锁都是可重入锁,而且 JDK 提供的所有现成的 Lock 实现类,包括 synchronized 关键字锁都是可重入的

这就是一个典型的加两次锁的情况,但是java中的synchronized是可重入锁,当发生锁冲突的时候,会进行检测,如果此时占有锁的线程和冲突的线程是同一个线程,那就会直接放行不会发生锁冲突的现象。

以上就是本篇博客的全部内容。

【剧前爆米花--爪哇岛寻宝】常见的锁策略——乐观锁、读写锁、重量级锁、自旋锁、公平锁、可重入锁等相关推荐

  1. 【剧前爆米花--爪哇岛寻宝】初识Java,了解Java代码的运行机制及JDK,JRE,JVM等

    作者:困了电视剧 专栏:<JavaSE语法与底层详解> 文章分布:这是一篇知识点较为基础的文章,我会先将JavaSE相关的知识给罗列一遍,然后在后续的文章中会对其中重要的点再逐一进行底层剖 ...

  2. 【剧前爆米花--爪哇岛寻宝】运算符知识梳理

    作者:困了电视剧 专栏:<JavaSE语法与底层详解> 文章分布:这是一篇知识点较为基础的文章,我会先将JavaSE相关的知识给罗列一遍,然后在后续的文章中会对其中重要的点再逐一进行底层剖 ...

  3. 【剧前爆米花--爪哇岛寻宝】MySQL中索引和事务

    作者:困了电视剧 专栏:<MySQL数据库> 文章分布:这是一篇关于Java中异常类的文章,在本篇文章中详细讲解了异常的使用逻辑和底层的执行过程,如有疏漏,欢迎大佬指正! 目录 索引 用法 ...

  4. 常见锁策略—乐观锁悲观锁

    目录 1.乐观锁&悲观锁 1.1 乐观锁的定义 1.2 乐观锁的实现(CAS机制) 1.3 乐观锁存在的问题:ABA问题 1.4 悲观锁 2.公平锁&非公平锁 3.读写锁 4.独占锁& ...

  5. 可重入锁与不可重入锁以及常见的死锁现象

    可重入锁和不可重入锁 Mutex可以分为递归锁(recursive mutex)和非递归锁(non-recursive mutex). 可递归锁也可称为可重入锁(reentrant mutex), 非 ...

  6. 常见的锁策略、synchronized中的锁优化机制

    一.常见的锁策略 锁策略,和普通程序猿基本没啥关系,和 "实现锁" 的人才有关系的 这里所提到的锁策略,和 Java 本身没关系,适用于所有和 "锁" 相关的情 ...

  7. 别翻了,常见的锁策略就在这里了~

    咱们其他也就不多说了,就直奔主题了~ 1.乐观锁 VS 悲观锁 悲观锁:总是假设最坏的情况,每次取拿数据的时候都认为别人会修改,所以在拿数据的时候都会上锁,这样别热你想拿到这个数据就会阻塞直到它拿到锁 ...

  8. 常见锁策略_CAS(Compare And Swap)_synchronized优化

    目录 1.常见锁策略 1.1乐观锁vs悲观锁 1.2轻量级锁vs重量级锁 1.3自旋锁vs挂起等待锁 自旋锁 挂起等待锁 1.4互斥锁vs读写锁 1.5公平锁vs非公平锁 公平锁 非公平锁 1.6可重 ...

  9. Java名字的由来:Java和印尼爪哇岛有什么关系?

    作者:魔幻王 链接:https://www.zhihu.com/question/41591996/answer/91612849 来源:知乎 既然没人回答,我说一说,根据真实故事添油加醋. 大概就像 ...

最新文章

  1. 还不错的Table样式和form表单样式
  2. DataGridView 里数据的动态明细 DataGridView GridView
  3. 专家周 |360精确搜索VS今日头条精准推荐算法
  4. 云炬WEB开发笔记2-4 Sublime使用技巧
  5. 2008年初看的书[带简评]
  6. 第五模块·WEB开发基础-第2章JavaScript基础
  7. mysql查询缓存到redis_php查询mysql并缓存到redis
  8. frisby用例动态链
  9. .net 4.0新特性-自旋锁(SpinLock)
  10. 幼儿园绘本图书借阅小程序
  11. 计算机工业设计id,我所认识的工业设计(ID)
  12. java格林威治时间转换_JAVA 格式化格林威治时间(Wed Aug 01 00:00:00 CST 2012)格式转换...
  13. 大数据技术如何影响企业决策?
  14. 服务器快速操作pc文件,如何将普通pc做服务器
  15. ssm+layui 超市管理系统 大学期末作业详解(1)
  16. 乌班图linux怎么连手机热点,ubuntu 16.04 设置位wifi热点 方法(手机可链接)亲测可用...
  17. 从0开始安装k8s1.25【最新k8s版本——20220904】
  18. 注册、登录、退出登录
  19. 蔡先生论道大数据之一 : 大数据由来
  20. 华为手机大变?余承东被传离职转岗,进军美国受阻惹的祸?

热门文章

  1. C++ 面向对象思想
  2. 夜天之书 #25 Evolving TiDB Governance
  3. 用python处理股票龙头股_Python股票分析系列:基础股票数据操作(二)
  4. 程序员什么时候该考虑辞职?
  5. Java中retainAll方法使用
  6. 台式计算机折旧年限,最新税法规定固定资产电脑折旧年限是多少年
  7. java调用c语言的动态库,hu-unix下面java调用c语言动态链接库.docx
  8. java命名规范法则大全
  9. DotNetCore调用Https
  10. oracle跨表空间报错ORA00942,解决oracle报错ora-00704 ora-00604 ora-00942 启动不了数据库...