Java虚拟机--线程安全与锁优化
2016-08-04 10:49
260 查看
线程安全
在Java中可以对各种操作共享数据分为以下5类:不可变、绝对线程安全、相对线程安全、线程兼容、线程对立。1)不可变
用final修饰的基本变量、行为不会对自己的状态产生影响的对象(比如,把自己的状态设置为final的)、枚举类、java.lang.Nuncer的部分子类(Long,Double等的数值包装类)、BigInteger和BigDecimal等大数据类型。(AtomicInteger和AtomicLong并非不可变)2)绝对线程安全
即使,一个对象的自身行为全部是同步的,在多线程环境下也不能保证线程的绝对安全。3)相对线程安全
Java的所谓得线程安全的集合类大部分都是相对线程安全的,需要在调用端加上额外的同步操作。4)线程兼容
对象本身并不是线程安全,而是通过在调用端正确使用同步手段保证对象的线程安全。如ArrayList、HashMap等。5)线程对立
无论调用端采用哪种同步操作,都无法在多线程环境下并发使用的代码。线程安全的实现方法(虚拟机层次)
1)互斥同步
互斥是实现同步的一种手段,临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphone)都是互斥实现方式。Syncronized同步块,编译后会在同步块前后,加入monitorenter、monitorexit指令。线程阻塞或唤醒时,需要内核调度,要进行用户态核心态的切换,很耗时。虚拟机会进行优化,如自旋等待。
ReentrantLock,也可实现同步功能(lock、unlock、配合try/finally完成),而且比Syncronized多了高级功能:等待可中断、可实现公平锁、锁可绑定多个条件。如下图所示:
2)非阻塞同步
乐观同步策略3)无同步方案
可重入代码块:例如不依赖存储在堆上的数据和公用的系统资源线程本地存储:ThreadLocal的实现
锁优化
1)自旋锁与自适应锁
自旋锁:为了防止同步造成的阻塞对性能的影响,让获取不到锁的线程先进行一个忙循环(自旋),暂时不放弃CPU,这就是自旋锁。自适应锁:自旋时间不再固定,由历史情况计算时间(很智能啊~)
2)锁消除
编译器优化掉不需要的锁。3)锁粗化
如果检测到短时间内对同一个对象反复加锁(比如,在一个循环里面有同步代码块),就会把加锁范围扩大(比如,就扩大到循环外围),这样就只有枷锁一次。4)轻量级锁
对于绝大部分的锁,在整个同步周期都是不存在周期的,使用轻量级锁的话,在没有竞争时就不会有互斥的开销,若有竞争就会转化为重量级锁(在有竞争的情况下,轻量级锁比重量级锁更慢,有一个判断竞争的过程)。5)偏向锁
当拥有偏向锁的对象第一次被一个线程获取锁的时候,对象就会置为“偏向模式”,持有偏向锁的线程以后每次进入这个锁得同步块时,虚拟机可以不用任何同步操作。直到,另一个线程尝试获取此锁时,“偏向模式”宣告结束。相关文章推荐
- 使用EL表达式显示RedirectAttributes存放与FlashMap中的键值对
- Java review--JVM
- JVM调优总结
- Java review--反射
- Java使用Jetty实现嵌入式Web服务器及Servlet容器
- SpringMVC上传超过2M文件时不能正常返回异常信息到页面
- JAVA利用cmd命令行调用WINRAR解压及压缩
- JAVA 枚举类型使用(结合案例)
- eclipse安装SVN插件
- Dozer数据对象转换神器
- Mysql主从Java端实现
- struts2国际化
- Java中static的使用
- Java 中的事物
- struts2自定义拦截器
- Java时间戳与日期格式字符串的互转
- 使用Java发送GET、POST请求
- spring-aop
- Spring Boot入门
- springMVC拦截器、json转换器、统一异常处理在配置文件中配置