为了性能与使用的场景,Java实现锁的方式有非常多。而关于锁主要的实现包含synchronized关键字AQS框架下的锁,其中的实现都离不开以下的策略。

悲观锁与乐观锁

  • 乐观锁。乐观的想法,认为并发读多写少。每次操作的时候都不上锁,直到更新的时候才通过CAS判断更新。对于AQS框架下的锁,初始就是乐观锁,若CAS失败则转化为悲观锁。
  • 悲观锁。悲观的想法,认为并发写多读少。每次操作数据都上锁,即使别人想读也要先获得锁才能读。对于1.6以前的synchronized关键字,则是悲观锁的实现之一。

CAS无锁算法

全称为 Compare and Swap。CAS有三个操作数,内存值V,旧预期值(已获得的旧数据)A,修改新值B。当且仅当V与A的值相同(compare),才能把V替换为B(Swap)。其中Java中内存值可以通过volatile关键字标识获取,该关键词可以使变量对所有线程实时可见。

CAS算法在锁的应用非常广泛,java中concurrent包的高性能都是基于这个算法,可以说没有CAS,并发包的高性能也就不存在了。

重量级锁

悲观锁的一种。互斥使代码执行可以同步,但这种方式成本比较高,涉及到操作系统的调用阻塞,会造成一些系统资源的浪费。1.6以前,在Java中的即是监视器锁,把.java文件编程成.class文件后能看到synchronized关键字就是通过monitorenter和monitorexit这个两个字节码指令来实现的。

轻量级锁

由于在没有很多线程竞争的前提下,重量级锁会导致性能资源的浪费。每次判断是否无锁,无锁则建锁记录,有锁通过CAS去尝试获取锁(对比Mark Word)。该过程失败会让锁膨胀为重量级锁。

偏向锁

是轻量级锁的优化,适用于无多线程竞争。虽然轻量级锁在可以在较少线程竞争下,减少操作系统调用,减少互斥变量的产生。但在理想情况下,线程很少发生线程竞争,在轻量级锁中,还是会有比较多的CAS操作。在偏向锁中,有一个锁记录(Mark word)标记为偏向,指向当前线程。若该指向不变,则只需要判断记录是否有被切换。如果被切换了,尝试CAS替换指向,后续一直执行同步代码块。当CAS替换指向失败,则说明存在多线程竞争,此时锁会膨胀为轻量级锁。

自旋锁

是锁竞争失败后执行的策略之一,对应的有阻塞的锁。在线程竞争锁失败后,阻塞的锁会把线程阻塞,直到有信号唤起才能继续执行线程,此过程会涉及用户态与系统态的转换,产生性能消耗。而自旋锁在锁竞争失败后,会把线程做自旋,避免线程进入阻塞。在自旋过程中,会不断的尝试去竞争锁。
但如果线程一直自旋都获取不到锁,也会产生很多CPU的性能消耗,所以也有一个自适应的自旋锁(控制自旋的时间)解决这个问题。


更多技术文章、精彩干货,请关注
博客:zackku.com
微信公众号:Zack说码
[](http://qiniu.zackku.com/%E6%89%AB%E7%A0%81_%E6%90%9C%E7%B4%A2%E8%81%94%E5%90%88%E4%BC%A0%E6%92%AD%E6%A0%B7%E5%BC%8F-%E5%BE%AE%E4%BF%A1%E6%A0%87%E5%87%86%E7%BB%BF%E7%89%88.png

Java多线程——锁概念与锁优化的更多相关文章

  1. Java多线程专题5: JUC, 锁

    合集目录 Java多线程专题5: JUC, 锁 什么是可重入锁.公平锁.非公平锁.独占锁.共享锁 可重入锁 ReentrantLock A ReentrantLock is owned by the ...

  2. Java多线程6:Synchronized锁代码块(this和任意对象)

    一.Synchronized(this)锁代码块 用关键字synchronized修饰方法在有些情况下是有弊端的,若是执行该方法所需的时间比较长,线程1执行该方法的时候,线程2就必须等待.这种情况下就 ...

  3. Java多线程5:Synchronized锁机制

    一.前言 在多线程中,有时会出现多个线程对同一个对象的变量进行并发访问的情形,如果不做正确的同步处理,那么产生的后果就是“脏读”,也就是获取到的数据其实是被修改过的. 二.引入Synchronized ...

  4. Java多线程--基础概念

    Java多线程--基础概念 必须知道的几个概念 同步和异步 同步方法一旦开始,调用者必须等到方法调用返回后,才能执行后续行为:而异步方法调用,一旦开始,方法调用就立即返回,调用者不用等待就可以继续执行 ...

  5. java 多线程总结篇4——锁机制

    在开发Java多线程应用程序中,各个线程之间由于要共享资源,必须用到锁机制.Java提供了多种多线程锁机制的实现方式,常见的有synchronized.ReentrantLock.Semaphore. ...

  6. Java多线程4:synchronized锁机制

    脏读 一个常见的概念.在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过 ...

  7. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  8. java 多线程12 : 无锁 实现CAS原子性操作----原子类

    由于java 多线程11:volatile关键字该文讲道可以使用不带锁的情况也就是无锁使变量变成可见,这里就理解下如何在无锁的情况对线程变量进行CAS原子性及可见性操作 我们知道,在并发的环境下,要实 ...

  9. JAVA多线程提高八:线程锁技术

    前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...

随机推荐

  1. codeforces 1060 D

    https://codeforces.com/contest/1060/problem/D 题意:你可以用1个及以上的圆桌,给n个人排座位,每个人左边需要有Li个空凳子,右边需要有Ri个空凳子,问你最 ...

  2. idea 导入spring 源码注意的问题

    问题:idea导入spring 源码的步骤是: 首先从官网下载spring的源码:git clone https://github.com/spring-projects/spring-framewo ...

  3. MyBatis的SQL语句映射文件详解(二)----增删改查

    1.select语句 public List<User> findUser() {  // TODO Auto-generated method stub    List users= ( ...

  4. java 线程 join(wait) 后,是如何唤醒

    概要:锁是线程,锁对象执行完毕后,会调用自身对象上的notify(); Join 方法:本质上还是根据wait方法实现的.分析join源码发现join方法本身是使用了synchronized修饰符的. ...

  5. IDEA中如何使用svn

    1.安装tortoiseSVN客户端时,这里一定要勾选上,否则使用时会报错. 2.安装好之后,想启用idea的SVN插件还需要在idea配置一下,file - setting 按钮打开设置界面 或者( ...

  6. swift xcode设置 ,代码折叠,全局折叠 快捷键

    在preference text editing 里面打开 function 折叠的项, 折叠方法快捷键: option+command +left/right 全局折叠快捷键: shift+opti ...

  7. CF#328 (Div. 2) C(大数)

    C. The Big Race time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  8. vim的插件管理与配置

    vim作为我做喜欢的编辑器,可扩展性几乎是没有尽头的,前阵子一直在配置这.vimrc文件,原来搞过配色文件,现在主要就自动补全来设置下,同时作为自己配置的记录文档.……………………………………………… ...

  9. bayer转dng实现过程记录

    前言 项目中需要将imx185出来的raw数据转成dng格式,一开始认为很简单的事情,后面才发现还是挺复杂的!!!首先考虑的是不写任何代码,直接用adobe提供的转换工具来转,结果发现,不仅是adob ...

  10. HTTP===返回结果的HTTP状态码

    HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作. 1.状态码告知从服务器端返回的请求结果 状态码的职责是当客户端向服务器端发送请求时,描述返 ...