目录
Java代码再编译后会变成Java字节码,字节码被类加载器加载到JVM中,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的病大机制依赖于JVM的实现和CPU指令。
一、volatile 的应用
volatile是轻量级的synchronized,volatile再多处理器开发中保证了共享变量的可见性,意思是当啊ige线程修改一个共享变量时,另外一个线程能读到这个修改的值。比使用synchronized的使用和执行成本更低,不会引起线程上下文的切换和调度。
1、volatile的定义和实现原理
排它锁保证线程单独获得共享变量,从而共享变量可以被准确和一致的更新。
有volatile变量修饰的共享变量,再进行写操作的时候,转变成汇编代码,会多出lock前缀的指令,
lock指令在多核处理器下会引发:
- 将当前处理器缓存行的数据协会到系统内存。
- 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。
对声明了volatile的变量进行写操作时,JVM就会向处理器发送一条lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。在多处理器下,为了保证各个处理器的缓存是一直的,就会实现一个缓存一致协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了。当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存找那个把数据读到处理器缓存里。
2、volatile的使用优化
JDK 7 的并发包里新增一个队列集合LinkedTransferQueue,在使用volatile变量时,用一种追加字节的方式来优化队列出队和入队的性能。
追加到64字节能够优化处理器性能。
在缓存非64字节宽度的处理器或者共享变量频繁的被写时,就不需要追加到64 字节了。
二、synchronized 的实现原理与应用
重量级锁 synchronized
Java SE 1.6 为了减少获得锁和释放锁带来的性能消耗,引入了偏向所和轻量级锁。
利用synchronized 实现同步,Java中的每一个对象都可以作为锁,集体有三种形式:
- 对于普通同步方法,锁是当前实例对象
- 对于静态同步方法,锁是当前类的class对象
- 对于同步方法块,锁是synchronized 括号里配置的对象
JVM基于进入和退出monitor实现方法和代码块的同步,代码块是由monitorenter和monitorexit指令实现的。
1、Java对象头
synchronized用的锁是存在Java对象头里的,
2、锁的升级与对比
锁的级别:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态
锁只能升级,不能降级。
偏向锁
当一个线程频繁的多次获得锁,为了让线程获得锁的代价降低,引入了偏向锁。
偏向锁的撤销:等到竞争出现才释放锁的机制。
偏向锁的关闭:JVM参数:关闭延迟:-XX:BiasedLockingStartupDelay=0。关闭偏向锁:-XXUseBiasedLocking=false
轻量级锁
3、锁的优缺点
三、原子操作的实现原理
处理器如何实现院子操作
1)使用总线锁保证原子性
2)使用缓存锁保证原子性
使用循环CAS实现原子操作
package cn.edu.Concurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class Counter {
private AtomicInteger atomicInteger = new AtomicInteger(0);
private int i = 0;
public static void main(String[] args){
final Counter counter = new Counter();
List<Thread> ts = new ArrayList<>(600);
long start = System.currentTimeMillis();
for(int j = 0; j < 100; j++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i< 1000 ; i++){
counter.safeCount();
counter.count();
}
}
});
ts.add(t);
}
for(Thread t : ts) t.start();
for(Thread t : ts){
try{
t.join();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println(counter.i);
System.out.println(counter.atomicInteger.get());
System.out.println(System.currentTimeMillis() - start);
}
private void safeCount(){
for(;;){
int i = atomicInteger.get();
boolean suc = atomicInteger.compareAndSet(i, ++i);
if(suc) break;
}
}
private void count(){
i++;
}
}