锁优化及注意事项

  • 有助于提高锁的性能

    • 减小所持有时间:例如不要对方法直接加锁,而是在方法中对具体访问临界资源的代码加锁
    • 减小锁粒度:如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. SpringBoot项目部署初体验【Docker】

    前言 一个微服务项目,小到几个模块,大到十几二十几个模块,每个模块都是单独的SpringBoot工程,这么多模块的部署,部署成本真的很高,而且每个服务的部署,都是手动部署,打成war或者jar ?,一 ...

  2. spring约束

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. 【基础】Linux软件安装方法

    linux中wget .apt-get.yum rpm区别 wget 类似于迅雷,是一种下载工具, 通过HTTP.HTTPS.FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理 名字是Wo ...

  4. cf期望概率专题

    cf1009E:求到第i段期望和的比较困难,但是单独求每段的期望是比较容易的,所以单独对每段求和,然后累计总和 E[i]=1/2*a1+1/4*a2+...+1/2^(i-1)*ai-1+1/2^(i ...

  5. 基础课(一)Cisco Packet Tracer Student模拟器简单的运用

    一.相同设备之间用交叉线,不同设备之间用直通线 如上图中的简单的两个PC机相连,交叉线相连的两个PC机是能ping同,直通线相连的两台PC机不通,ipconfig可以查看本机设备的网络配置 time= ...

  6. 一些识别CMS的经验方法总结

    今天学到了一些识别CMS的快速方法,也算是一种信息收集经验的积累,在这里要感谢一下我的同事“gakki的童养夫”对我的大力支持. 如何判断网站的CMS? robots.txt文件 robots.txt ...

  7. Django框架(十一)—— 常用字段、参数、元信息、多对多关联关系

    目录 常用字段和参数 一.ORM字段 二.ORM参数 三.关系字段 1.ForeignKey 2.OneToOneFiled 3.ManyToManyField 四.元信息 五.多对多关联关系的三种方 ...

  8. Java 并发之原子性与可见性

    原子性 原子是世界上的最小单位,具有不可分割性.比如 a=0:(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作.再比如:a++: 这个操作实际是a = a + 1 ...

  9. html5语义化标签大全

    常见的语义化标签有 <article>.<section>.<nav>.<aside>.<header>.<footer> 详细 ...

  10. C# WinfForm 控件之dev报表 XtraReport (七)报表合并

    这个不是太难,新建两个报表 一个form窗体 窗体上放个documentView  代码如下 XtraReport2 xr2 = new XtraReport2(); xr2.CreateDocume ...