目录
2.volatile使long类型和double类型的变量是原子性
volatile的特点
1.volatile最主要的作用是保证内存可见性
volatile修饰变量:JVM中线程要读变量,每次从主内存读取,写入也保证写回主内存中。不在工作内存中存,内存可见性这个问题就不会出现了。volatile 90%的功能都是保护内存可见性。
import java.util.concurrent.TimeUnit;
public class WithOutVolatile {
//没有volatile修饰的话 主线程无法改变quit在主内存的值
volatile static boolean quit=false;
static class MyThread extends Thread{
@Override
public void run() {
long r=0;
while (quit==false){
r++;
}
System.out.println(r);
}
}
public static void main(String[] args) throws InterruptedException {
MyThread t=new MyThread();
t.start();
TimeUnit.SECONDS.sleep(5);
quit=true;
}
}
2.volatile使long类型和double类型的变量是原子性
JVM基本操作长度为32位处理int,short,byte,char,float类型的变量都是原子性的,处理String 类型的变量时,JVM保证引用的赋值时原子的,long类型和double类型的变量是64位的,所以不是原子性的,当这两个类型变量被volatile修饰时,这两个类型的变量就是原子性的。
3.volatile保证代码不被重排序
SomeObject s=new SomeObject();
a.根据类计算对象的大小,在内存中(堆)分配内存空间给该对象,memset(默认值);
b.对象的初始化过程:构造代码块,属性的初始化赋值;
c.把引用交给s;
一般的,执行顺序应该是a->b->c,实际中代码可能会自动优化,重排序成a->c->b。单线程两个顺序都不影响使用,多线程则可能会出错。
如果多线程调用重排序的顺序,在引用指向未初始化的对象的时候调用对象,就会出现错误。
使用volatile修饰 :volatile SomeObject s=new SomeObject();就不会出现这种重排序的状况,代码的执行顺序一定是a->b->c。
单例模式(singleton pattern)
首先得知,设计模式(design pattern):对一些解决通用问题的,经常书写的代码片段的总结与归纳。
单例模式:通过代码保护一个类,使得类在整个进程(应用)运行过程中有且只有一个对象。
单例模式整体上有两种模式:一种叫“饿汉模式”,一开始就初始化的(等不及)。一种叫“懒汉模式”,等用到的时候在初始化。
public class Star