锁优化及注意事项

  • 有助于提高锁的性能

    • 减小所持有时间:例如不要对方法直接加锁,而是在方法中对具体访问临界资源的代码加锁
    • 减小锁粒度:如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. mongodb客户端操作常用命令(续)

    之前有写过一篇mongodb客户端的操作常用命令 ,今天接着来记录分享一些关于mongodb账户权限设置的命令操作 上期mongodb客户端的操作常用命令地址:https://www.cnblogs. ...

  2. 解决SQLite中的 database is locked

    前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked ...

  3. Android中的gen文件为空或者不存在的处理方法

    Android中的gen文件时链接程序和XML中资源定义的桥梁,所以如果gen文件夹为空可能有以下的几个原因: 1.XML文件错误,这时可以检查res文件夹中的文件是否有错误 2.导入新的Androi ...

  4. 【C#技术】一篇文章搞掂:LLBL

    公司代码速查 ParameterBase.CurrentUser.UserId ICustomerDeskDetailManager customerDeskDetailManager = Clien ...

  5. PAT 1010 Radix(X)

    1010 Radix (25 分)   Given a pair of positive integers, for example, 6 and 110, can this equation 6 = ...

  6. shell cat 合并文件,合并数据库sql文件

    > 覆盖写入 >> append模式写入 ###################################################################合并数 ...

  7. on() 不支持hover事件

    因为 .hover() 是 jQuery 自己定义的事件… 是为了方便用户绑定调用 mouseenter 和 mouseleave 事件而已,它并非一个真正的事件,所以当然不能当做 .bind() 中 ...

  8. 2019河北省大学生程序设计竞赛(重现赛)J-舔狗 (拓扑排序)

    题目链接:https://ac.nowcoder.com/acm/contest/903/J 题意:给你 n 个舔狗和他喜欢的人,让你俩俩配对(只能和喜欢它的和它喜欢的),求剩下的单身狗数量. 思路: ...

  9. Java通道

    通道(Channel)是数据源和Java程序之间的开放连接,用于执行I/O操作.Channel接口在java.nio.channels包中.通道(Channel)接口只声明了两个方法:close()和 ...

  10. 百度编译器ueditor目录创建失败问题解决

    修改ueditor编辑器的文件Uploader.class.php   例如: vim protected/widget/ueditor/php/Uploader.class.php :283 if( ...