锁优化及注意事项

  • 有助于提高锁的性能

    • 减小所持有时间:例如不要对方法直接加锁,而是在方法中对具体访问临界资源的代码加锁
    • 减小锁粒度:如ConcurrentHashMap
    • 用读写锁代替独占锁
    • 锁分离:如LinkedBlockingQueue,由于读写分别在队首和队尾,所以不对整个队加锁而是对队首和队尾分别加锁
    • 锁粗化:当一个锁在某段时间对某一资源反复申请锁,可以现将锁分给此线程一段时间,阻塞其他线程
  • Java虚拟机的锁优化
    • 锁偏向:因为很有可能是同一个线程申请某个锁,所以如果一个线程获取了锁,那么就进入偏向模式,当此线程需要再次申请锁时,无需再进行同步操作。
    • 轻量级锁:如果偏向锁实效,虚拟机不会立即挂起线程,而是会简单地将对象头部作为指针,指向持有锁的线程堆栈的内部,来判断一个线程是否持有对象锁,如果线程获得轻量级锁成功,则进入临界区,否则当前线程酒会膨胀为重量级锁
    • 自旋锁:锁膨胀后,虚拟机为了避免线程在操作系统层面真正被挂起。系统会进行一次赌注,假设在不久的将来线程会获得锁,所有会让当前线程进行几个空循环,若经过几个时钟周期后获得锁,则进入临界区,否则真正挂起
    • 锁消除:虚拟机在JIT编译时,对运行上下文进行扫描,去除不可能存在共享资源的竞争的锁。主要只是指JDK一些内置API,如StringBuffer、Vector。
  • ThreadLocal:线程本地变量,为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
    • synchronized是用时间保证安全,ThreadLocal是用空间保证安全
    • 实现:
      • ThreadLocal类有一个内部类ThreadLocalMap,用来保存键值对,当前ThreadLocal为键,要存储的副本为值。每一个Thread都有一个ThreadLocalMap类型成员threadLocals用来保存键值对
      • 初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals
    • 详细说明:http://www.cnblogs.com/dolphin0520/p/3920407.html
  • 无锁:无锁是一种乐观的策略,他会假设对临界区资源的访问是没有冲突的。无锁策略使用一种叫做比较交换的技术(CAS--Compare and swap),一旦检测到冲突,就重试当前操作直到没有冲突为止。
    • 无锁没有竞争带来的系统开销,也没有频繁调度的开销
    • 算法:三个参数,V要更新的变量、E预期值、N新值。仅当V值等于E值时,才会将V值设为N值,否则认为其他线程做了更新。最后CAS返回当前V真实值。当多个线程同时使用CAS操作一个变量时,只有一个会胜出,其余均失败,失败的线程不会被挂起,而是再次尝试,也允许放弃。总之,CAS操作需要给出一个期望值,也就是你认为现在变量应该是什么样子,如果不如你所愿,说明变量已经被修改过了,你需要重新去读变量值,再修改。

Java 并发总结(三)的更多相关文章

  1. Java并发编程三个性质:原子性、可见性、有序性

      并发编程 并发程序要正确地执行,必须要保证其具备原子性.可见性以及有序性:只要有一个没有被保证,就有可能会导致程序运行不正确  线程不安全在编译.测试甚至上线使用时,并不一定能发现,因为受到当时的 ...

  2. 【JAVA并发第三篇】线程间通信

    线程间的通信 JVM在运行时会将自己管理的内存区域,划分为不同的数据区,称为运行时数据区.每个线程都有自己私有的内存空间,如下图示: Java线程按照自己虚拟机栈中的方法代码一步一步的执行下去,在这一 ...

  3. 【Java并发核心三】CountDownLatch、CyclicBarrier及Phaser

    个人感觉,看书学习还是需要“不求甚解”,因为一旦太过于计较小的得失,就容易钻牛角尖,学习进度也慢.我们完全可以先学一个大概,等到真正用到的时候再把那些细节丰富起来,就更有针对性. 所以,针对java并 ...

  4. 【Java并发编程三】闭锁

    1.什么是闭锁? 闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流.常见类型的Synchronizer包括信号量.关卡和闭锁). ...

  5. Java并发(三)线程池原理

    Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 1. 降低资源消耗.通过重复利用已创建的线程降低线程 ...

  6. Java并发编程 (三) 项目准备

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.案例环境初始化 1.环境搭建与准备 Spring Boot 项目,https://start.spr ...

  7. Java并发(三):重排序

    在执行程序时为了提高性能,提高并行度,编译器和处理器常常会对指令做重排序.重排序分三种类型: 编译器优化的重排序.编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序. 指令级并行的重排序 ...

  8. 和朱晔一起复习Java并发(三):锁(含锁性能测试)

    这个专题我发现怎么慢慢演化为性能测试了,遇到任何东西我就忍不住去测一把.本文我们会大概看一下各种锁数据结构的简单用法,顺便也会来比拼一下性能. 各种并发锁 首先,我们定一个抽象基类,用于各种锁测试的一 ...

  9. java并发系列(三)-----ReentrantLock(重入锁)功能详解和应用演示

    1. ReentrantLock简介 jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock.虽然在性能上ReentrantLock和synchronize ...

随机推荐

  1. Delphi中点击网页弹出的Alert对话框的确定按钮

    思路: 使用Windows API函数遍历窗口,查找指定标题的窗口,然后从该窗口查找确定按钮,向该按钮发送鼠标消息进行模拟点击.由于IE8由Alert弹出的网页对话框的标题是“来自网页的消息”,而IE ...

  2. goroutine 需要注意的一个小细节

    虽然goroutine 是并发执行的,但是它们并不是并行运行的.如果不告诉Go 额外的东西,同一时刻只会有一个goroutine 执行.利用runtime.GOMAXPROCS(n) 可以设置goro ...

  3. web跨域问题解决方案

    在前端开发及调试过程中总能遇到浏览器报如下错误: Response to preflight request doesn't pass access control check: No 'Access ...

  4. unittest框架学习笔记三之testsuite

    # coding=utf-8 '''created :2018/3/29 author:star project: testsuite'''import unittest,time,osfrom ba ...

  5. Hadoop生态上几个技术的关系与区别:hive、pig、hbase 关系与区别  Pig

    Hadoop生态上几个技术的关系与区别:hive.pig.hbase 关系与区别 Pig 一种操作hadoop的轻量级脚本语言,最初又雅虎公司推出,不过现在正在走下坡路了.当初雅虎自己慢慢退出pig的 ...

  6. mybatis执行test07测试类却显示test05测试类调用的sql语句出错

    1.测试类 @Test public void test07() { IStudentDao studentDao = new IStudentDaoImpl(); Student student = ...

  7. UI自动化ADB出现devices offline的解决方法

    终端运行如下命令即可解决: adb kill-server adb start-server adb remount

  8. JDK8新特性之Stream流

    是什么是Stream流 java.util.stream.Stream Stream流和传统的IO流,它们都叫流,却是两个完全不一样的概念和东西. 流可以简单的说是处理数据集合的东西,可以申明式流式A ...

  9. 高级UI晋升之常用View(三)中篇

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从ViewPager来介绍常用View:文章目录 一.简介 二.基本使用 ...

  10. java中Date日期类型的大小比较

    方法一:java.util.Date类实现了Comparable接口,可以直接调用Date的compareTo()方法来比较大小 String beginTime = "2018-07-28 ...