线程安全锁优化

线程安全:

当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要考虑额外的同步,或者在调用方进行任何其他协调操作,调用这个对象的行为都可以获得正确的结果,这个对象就是线程安全的。

Java语言中的线程安全

1.不可变 final Integer类

2.绝对线程安全

不管运行时环境如何,调用者都不需要任何额外的同步措施。

Java API标注是线程安全的一般都不是绝对线程安全。

3.相对线程安全(通常意义上的 线程安全)

Vector,HashTable ,Collections的SynchronizedCollection()方法

4.线程兼容

对象本身不是线程安全的,但是可以通过调用端正确地使用同步手段,可以保证在并发环境下安全的使用。ArrayList等

5.线程对立

无论是否使用同步手段,多线程环境下都不可使用。

System.setIn(),System.setOut()

线程安全的实现方法

1.互斥同步(阻塞同步,悲观锁)

互斥是方法,同步是目的。

synchronized关键字,编译后会生产moniterenter和moniterexit两个指令码。

ReentrantLock

优先使用synchronized

2.非阻塞同步(乐观锁)

CAS操作 sun.misc.Unsafe类的compareAndSwapInt(),compareAndSwapLong()

有ABA问题,可以用时间戳,version

3.无同步方案

可重入代码(幂等): 输入同样的数据,返回的结果都相同。

线程本地存储(只有一个线程使用)

一段代码的数据不与其他共享

锁优化

自旋锁与自适应自旋

自旋锁 “让等待锁的线程稍等一下”,执行一个忙循环,默认执行10次。

通过参数-XX:PreBlockSpin来更改。

自适应自旋锁:自旋时间不固定,由上一次在同一个锁上的自旋等待时间及锁的持有者状态来确定。

锁消除

依托逃逸分析的数据支持,例如线程私有的部分会去掉同步锁。

锁粗化

public void  a(){
while(i>0){
    synchronized{// 每次循环都加锁,好烦系统资源。
        do something();
    i++
       }
    }
}
//JVM自动优化为:
public void a(){
    synchronized{// 粗化仅仅加一次锁
        while(i>0){
        do something();
        i++
    }
    }
}

偏向锁:

消除无数据竞争情况下的同步原语。

这个锁会偏向第一个获取它的线程。该锁没有被其他线程获取,持有偏向锁的线程不需要进行同步。

轻量级锁:

基于Mark Word的CMS进行。

2个以上线程竞争同一个锁,会膨胀为重量级锁。

偏向锁、轻量锁状态转化及对象Mark Word的关系


Author: Juntech
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Juntech !
评论
  TOC